# XPなアプリケーションサーバ

Seasarは、eXtreme Programingの開発手法を使って開発されたアプリケーションサーバで、
シンプルなこと、徹底的にテストされていることが特徴です。
Webの機能は、Jettyを使っています。
データベースとして、HSQLDBも組み込まれているので、ダウンロードしてすぐに
様々な機能を試してみることができます。
また、シーサープラグインによって、Eclipseで快適に開発することもできます。

- 稼働環境
- インストール
- 開始と終了
- Jettyの設定
- Webアプリケーションのデプロイ
- シーサープラグイン
- シーサープロジェクト
- プロパティエディタ
- HSQLDBの設定
- HSQLDBのSQL構文
- コネクションプールの設定
- デモデータの準備
- クライアントの設定
- コネクションプールへの接続
- トランザクション処理
- Tomcatの利用
- Seasarサービス

## 稼働環境

JDK1.4とEclipse2.1.1以上が必要です。

## インストール

ダウンロードしたseasarsetupXXX.jarを適当なディレクトリにコピーして、 jar xf seasarsetupXXX.jarで解凍します。
seasarというディレクトリができるので、今後このディレクトリを$SEASAR_HOMEと 呼ぶことにします。
バージョン1.3以上のantがまだインストールされていないなら
コマンドラインから実行できるようにするために、
$SEASAR_HOME/binをPATH環境変数に加えてください。
コマンドラインから、ant -versionを実行して、バージョンが表示されればOKです。
これで、Seasarのインストールはこれで終了です。

## 開始と終了

Windowsの場合、$SEASAR_HOME/bin/startSeasar.batをダブルクリックします。
Unixの場合、$SEASAR_HOME/binにcdしてから、./startSeasar.shを実行します。

    INFO  2003-04-01 21:03:59,183 org.seasar.system.Seasar
    [ISSR0001]seasar started

のように表示されればOKです。 ブラウザから、http://localhost:8080/にアクセスし、
SeasarのWelcomeページが表示されることも確認してください。

終了は、Windowsの場合、$SEASAR_HOME/bin/shutdownSeasar.batをダブルクリックします。
Unixの場合、$SEASAR_HOME/binにcdしてから、./shutdownSeasar.shを実行します。
$SEASAR_HOME/logs/seasar.logの最後に

    INFO  2003-04-01 22:30:37,678 org.seasar.system.Seasar
    [ISSR0003]seasar shutdown

のように表示されればOKです。
Seasarのログは、$SEASAR_HOME/logsに書き出されます。
まだ、Seasarを終了させていない場合は、ここで終了させてください。

## Jettyの設定

Jettyの設定は、$SEASAR_HOME/classes/jetty.xmlで行います。
通常は、何もいじる必要はありません。詳しい設定内容は、 Jettyのホームページで確認してください。

## Webアプリケーションのデプロイ

Webのアプリケーションをデプロイするには、
warファイル、あるいは、warファイルを解凍したディレクトリを
$SEASAR_HOME/webappsにコピーします。
Seasarが起動中なら、$SEASAR_HOME/bin/restartJetty.bat(Unixの場合restartJetty.sh)を実行します。
Seasarが起動していないなら、単にSeasarを再起動するだけでOKです。
現状では、Webアプリケーションのホットデプロイには対応していませんが、
Jettyの起動・終了は一瞬なので、どきどきしながらホットデプロイされるのをまつより、
手動で行ったほうが、すっきりすると思っています。

## シーサープラグイン

実は、Seasarの起動・停止・再起動・Jettyの再起動といった処理は、
Eclipseから簡単に行うことができます。
Seasarプラグインの設定は次のように行います。
Eclipseをインストールしたディレクトリを$ECLIPSE_HOMEと呼ぶことにします。
Seasarプラグインを既にインストール済なら、$ECLIPSE_HOME/pluginsから削除します。
$SEASAR_HOME/plugins/org.seasar.eclipse_x.x.xを$ECLIPSE_HOME/pluginsにコピーして
Eclipseを再起動します。
Eclipseのウィンドウ->設定のシーサーのシートでシーサーホームを設定します。
次にEclipseのウィンドウ->パースペクティブのカスタマイズを選び
その他のツリーを開いて、シーサーをチェックしてOKをクリックします。
シーサーがメニューに現れるので、起動・停止・再起動・Jettyの再起動と
いった処理を簡単に行うことができます。

## シーサープロジェクト

Eclipseでシーサープロジェクトを作って開発すると、
そのまま、デプロイされたWebApplicationとして、
Jettyに認識されるので、Jettyを再起動するだけで、
ブラウザを使ったテストを行うことができます。
メニューから、ファイル->新規->プロジェクト->Java->シーサープロジェクトを選んで、
次へボタンをクリックします。
プロジェクト名をexamplesとし、終了ボタンをクリックします。
パッケージ・エクスプローラーでexamplesプロジェクトを右クリックし、
最新表示を実行した後に、プロジェクトのツリーを展開すると、
WEB-INF/src,WEB-INF/classes,WEB-INF/libが作成され、
必要なファイルが既にコピーされている事がわかります。
Javaのビルドパスも設定済みなので、面倒な設定を行うことなく
すぐに開発に取り掛かることができます。

次にexamplesプロジェクトをインポートします。
examplesプロジェクトを右クリックして、インポート->ファイルシステムを選びます。
ソースディレクトリを$SEASAR_HOME/examplesにし、左側のツリーのexamplesディレクトリを
チェックし、終了ボタンをクリックします。
これで、examplesプロジェクトが完成しました。
Seasarをまだ起動していない場合は、起動してください。
既に起動済みの場合は、Jettyを再起動します。
起動しているかどうかあやふやな場合(笑)は、Seasarを再起動します。

ブラウザから、 http://localhost:8080/examples/jsp/now.jspにアクセスします。

    Tue Oct 07 19:54:26 JST 2003

のようになれば、設定はうまくいってます。

WebApplicationのコンテキストパスは、後から変更することもできます。
変更は、プロジェクトを右クリックして、プロパティ->シーサーのページで行います。
シーサープロジェクトであるのチェックをはずすと、jetty.xmlからWebApplicationの
設定が削除されます。
シーサープロジェクトであるをチェックしなおすと、jetty.xmlにWebApplicationの
設定を再追加することもできます。

## プロパティエディタ

シーサープラグインを使えば、日本語を含んだ*.propertiesも簡単に扱えます。
これまでのように、native2asciiを実行する必要もありません。
メニューのウィンドウ->設定->ワークベンチ->ファイルの関連付けで
*.propertiesを選び、シーサープロパティエディタをデフォルトに指定します。
Eclipseから*.propertiesを作成して、日本語で入力し保存すると、
自動的にユニコードでエスケープされます。
ユニコードでエスケープされた*.propertiesを読み込んだときは、日本語で表示されます。

## HSQLDBの設定

HSQLDBの設定は、$SEASAR_HOME/classes/seasar-config.xmlのHsqldbServiceの
プロパティを設定することで行います。
最初は特に変える必要はないでしょう。
各プロパティの意味は次のとおりです。

名前 | 説明
--- | ---
    database
| データベース名を設定します。 $SEASAR_HOME/dataにデータベース名.拡張子のファイルが作成されます。 データベースが存在していない場合、自動的に作成されます。 各ファイルの意味は、データベースの構成ファイル を参照してください。
    port
| JDBC Driverの接続を受け付けるポートです。デフォルトは、9001になります。
    silent
| falseの場合、HSQLDB自身の詳細なメッセージをコンソールに書き出します。
    trace
| trueの場合、JDBCの詳細なメッセージをコンソールに書き出します。
    compact
| trueの場合、SHUTDOWN時に、CACHED TABLEのデータを再作成して、 データベースのサイズをコンパクトにします。 CASHED TABLEの詳細は、テーブルの種別を参照してください。
    checkpointInterval
| HSQLDBに対して、CHECKPOINTを発行する間隔を指定します。単位は秒です。 0だとCHECKPOINTは発行しません。
    retryCount
| Seasarは、HSQLDBを非同期に開始させているため、 本当に開始したことを確かめるために 非同期開始後、1秒おきにHSQLDBにSQL文を発行しています。 エラーが起きなければ、HSQLDBが起動済みとみなして、 後続のサービスを起動し、エラーが起きたら、retryCountの間、 SQL文を再発行して起動チェックを続けます。 データ量が増えて、HSQLDBの開始が遅くなった場合には、 retryCountを増やしてください。

#### データベース構成ファイル

HSQLDBのデータベースは、$SEASAR_HOME/dataディレクトリに作成され、
以下のファイルで構成されます。

名前 | 説明
--- | ---
    データベース名.properties
| データベースごとの設定を行います。 各項目の意味は、データベース名.propertiesの詳細 を参照してください。
    データベース名.script
| テーブルの定義とMEMORY TABLEのデータが書き込まれます。 通常にCREATE TABLEをするとMEMORY TABLEが作成されます。 MEMORY TABLEの詳細は、テーブルの種別を参照してください。
    データベース名.data
| CACHED TABLEのデータが書き込まれます。 CACHED TABLEの詳細は、テーブルの種別を参照してください。
    データベース名.backup
| 1番最後にSHUTDOWN, CHECKPOINTしたときのCACHED TABLEのデータを ZIP形式で圧縮したファイルです。

#### データベース名.propertiesの詳細

データベースごとの設定を行います。
各プロパティの意味は以下のとおりになります。

プロパティ名 | 説明
--- | ---
readonly | デフォルトはfalse。 trueの場合、データベースを更新することができなくなります。
sql.month | デフォルトはtrue。 trueの場合、month(Date)が1-12を返します。 falseの場合、0-11を返します。
sql.enforce_size | デフォルトはfalse。 trueの場合、VARCHARやCHARACTERのデータ型の値が、 テーブルの定義にあわせて、カットされたりパディングされたりします。 falseの場合、なにもしません。
sql.compare_in_locale | CHARACTER、VARCHARデータ型で、ソートするときに JREのロケールに従うかどうかを表します。 デフォルトはfalse。 trueの場合、現在のJREのロケールに従ってソートされます。 falseの場合、POSIX標準にしたがってソートされます。 CACHED TABLEを含むデータベースの場合、この値を変更すると インデックスがおかしくなります。 正しく変更するためには、Seasarを停止させた後、値を変更し HsqldbServiceのcompactプロパティをtrueにして Seasarを起動し、すぐに停止させてください。 停止させるときに、HSQLDBに対して、SHUTDOWN COMPACTを実行しているので インデックスが再作成されます。 その後、compactプロパティを元に戻して、Seasarを起動しなおします。
sql.strict_fk | バージョン1.7.1以降は、設定しても無視されます。
sql.strong_fk | バージョン1.7.1以降は、設定しても無視されます。
hsqldb.cache_scale | CACHED TABLEのデータがメモリ内で、2^hsqldb.cache_scaleのサイズ分 キャッシュされます。 デフォルトは14で、8-16でなければいけません。
hsqldb.log_size | 自動CHECKPOINTに達していなくても、メモリ上のlogのサイズが 指定した値を超えると、CHECKPOINTが実行されます。 単位は、Mバイトで、デフォルトは200です。
hsqldb.gc_interval | GCを強制的に実行するインターバルを指定します。 デフォルトは、0なのでGCは強制されません。 通常は0以外を設定すべきではありません。

#### テーブルの種別

HSQLDBは、一時的なテーブルと3つの永続的なテーブルをサポートしています。

一時的なテーブルは、CREATE TEMP TABLE文で作成します。
データはメモリ上に保存され、Connectionがクローズされるとデータも消えます。

永続的なテーブルは、MEMORY、CACHED、TEXTの3つがあります。

MEMORY TABLEは、CREATE TABLE文で作成します。
すべてのデータはメモリと.scriptファイルに保存されます。
起動時に、.scriptファイルが読み込まれて、メモリにテーブルの内容が
再作成されます。

CACHED TABLEは、CREATE CACHED TABLE文で作成します。
hsqldb.cache_scaleによって計算されるサイズまでは、
メモリ上にデータが保存され、それを超えると.dataファイルにデータが書き出されます。
大量のデータを扱えますが、速度は、MEMORY TABLEより遅くなります。

TEXT TABLEは、CREATE TEXT TABLE文で作成します。
詳細は、TEXT TABLEのマニュアル を参照してください。

#### DatabaseManager

HSQLDBに接続するためのユーティリティとして、$SEASAR_HOME/binに
runHsqldbManagerが用意されています。
起動すると、接続のTypeを聞かれます。
HSQL Database Engine Serverを選んで、OKをクリックすると
HSQLDBに接続できます。SHUTDOWNは、実行しないでください。

## コネクションプールの設定

データベースに接続するためには、コネクションプールの設定をする必要があります。
コネクションプールの設定は、$SEASAR_HOME/classes/connectionpool-config.xmlに対して 行います。

connectionPoolタグのdataSourceName属性で、このコネクションプールは 識別されます。
connectionPoolタグは、複数記述することができますが、
その中で、dataSourceName属性の値はユニークでなければなりません。

jndiName属性にJNDIからルックアップするときの名前を指定します。
慣例として、コネクションプールのJNDI名は、jdbc/dataSourceNameとします。

xaDataSourceClassName属性にjavax.sql.XADataSourceインターフェースを
実装したクラス名を指定します。JDBC DriverがXAに対応していない場合、
org.seasar.sql.XADataSourceImplを指定します。
XA機能をまともに実装できているJDBC Driverは少ないので、
通常は、org.seasar.sql.XADataSourceImplを指定します。

timeout属性で、コネクションをクローズしてから、
プールでキープされる時間(秒)を指定します。
指定した時間を過ぎると、コネクションは破棄されます。

poolSize属性で、同時にアクティブになれる
コネクションの数を指定します。
この数を超える要求があると、コネクションがプールに返されるまで
その要求はブロックされます。

propertyタグで、xaDataSourceClassNameで指定したクラスのインスタンスに対する
プロパティを指定します。org.seasar.sql.XADataSourceImplの場合、
driverClassName,URL,user,passwordを下記のように設定します。
下記の例は、HSQLDB、Oracle、PostgreSQLの場合です。

connectionpool-config.xmlをセーブしてください。
これで、サーバの設定は終了です。

    <connectionPools>

        <connectionPool
            dataSourceName="hsqldb"
            jndiName="jdbc/hsqldb"
            xaDataSourceClassName="org.seasar.sql.XADataSourceImpl"
            timeout="600"
            poolSize="20">
            <properties>
                <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
                <property name="URL" value="jdbc:hsqldb:hsql://localhost:9001"/>
                <property name="user" value="sa"/>
                <property name="password" value=""/>
            </properties>
        </connectionPool>

        <connectionPool
            dataSourceName="oracle"
            jndiName="jdbc/oracle"
            xaDataSourceClassName="org.seasar.sql.XADataSourceImpl"
            timeout="600"
            poolSize="20">
            <properties>
                <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="URL" value="jdbc:oracle:thin:@localhost:1521:testdb"/>
                <property name="user" value="scott"/>
                <property name="password" value="tiger"/>
            </properties>
        </connectionPool>

        <connectionPool
            dataSourceName="postgres"
            jndiName="jdbc/postgres"
            xaDataSourceClassName="org.seasar.sql.XADataSourceImpl"
            timeout="600"
            poolSize="20">
            <properties>
                <property name="driverClassName" value="org.postgresql.Driver"/>
                <property name="URL" value="jdbc:postgresql://localhost/testdb2"/>
                <property name="user" value="scott"/>
                <property name="password" value="tiger"/>
            </properties>
        </connectionPool>

    </connectionPools>

## デモデータの準備

データベースに接続するプログラムを動かすために$SEASAR_HOME/sqlの スクリプトを実行します。
オラクルの場合はdemo-oracle.sql、HSQLDBの場合はdemo-hsqldb.sqlを実行します。
HSQLDBの場合は、既にデモデータが用意されているので、
実際に実行する必要はありません。
他のデータベースをお使いの方は、データベースにあわせてスクリプトを修正してください。

## コネクションプールへの接続

コネクションプールには、JNDI経由(javax.naming.InitialContext)で接続します。
どこに接続するのかは、InitialContextのコンストラクタに渡すPropertiesで 設定します。

    Properties env = new Properties();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "org.seasar.naming.NamingContextFactory");
    env.put(Context.PROVIDER_URL, "localhost:1108");
    InitialContext ctx = new InitialContext(env);

Context.INITIAL_CONTEXT_FACTORYに設定する値は、
アプリケーションサーバごとに異なりますが、
Seasarの場合は、org.seasar.naming.NamingContextFactoryを指定します。

Context.PROVIDER_URLでSeasarの場所を指定します。
ホスト名:ポート番号の形式です。
ポート番号は、$SEASAR_HOME/classes/seasar-config.xmlの
portプロパティの値とあわせる必要があります。デフォルトは、1108です。

    <service className="org.seasar.system.RMIAdaptorService">
        <properties>
            <property name="port" value="1108"/>
        </properties>
    </service>

InitialContextからjavax.sql.DataSourceを取得します。
lookup()の引数に指定するJNDI名は、$SEASAR_HOME/classes/connectionpool-config.xmlで connectionPoolにつけたjndiNameになります。

後は、javax.sql.DataSource#getConnection()で、コネクションを取り出し、
JDBCの処理を行うことができます。

    DataSource ds = (DataSource) ctx.lookup("jdbc/hsqldb");
    Connection con = ds.getConnection();

#### examples.org.seasar.ConnectionPoolExample

    package examples.org.seasar;

    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Properties;

    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.sql.DataSource;

    public class ConnectionPoolExample {

        private static final String FACTORY =
            "org.seasar.naming.NamingContextFactory";
        private static final String URL = "localhost:1108";
        private static final String JNDI_NAME = "jdbc/hsqldb";
        private static final String SQL = "SELECT ename FROM emp";

        public static void main(String[] args) {
            try {
                Properties env = new Properties();
                env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
                env.put(Context.PROVIDER_URL, URL);
                InitialContext ctx = new InitialContext(env);
                DataSource ds = (DataSource) ctx.lookup(JNDI_NAME);
                Connection con = null;
                Statement stmt = null;
                ResultSet rs = null;
                try {
                    con = ds.getConnection();
                    stmt = con.createStatement();
                    rs = stmt.executeQuery(SQL);
                    while (rs.next()) {
                        System.out.println(rs.getString("ename"));
                    }
                } finally {
                    if (rs != null) {
                        rs.close();
                    }
                    if (stmt != null) {
                        stmt.close();
                    }
                    if (con != null) {
                        con.close();
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

このプログラムを実行して下記のようなエラーになった場合は、
まだSeasarが開始されていません。

    javax.naming.NamingException: java.net.ConnectException: Connection refused: connect
        at org.seasar.naming.NamingUtil.convertNamingException(NamingUtil.java:14)
        at org.seasar.naming.NamingServerWrapper.lookup(NamingServerWrapper.java:44)
        at org.seasar.naming.NamingContext.lookup(NamingContext.java:105)
        at org.seasar.naming.NamingContext.lookup(NamingContext.java:98)
        at javax.naming.InitialContext.lookup(InitialContext.java:347)
        at examples.org.seasar.ConnectionPoolExample.main(ConnectionPoolExample.java:26)
    Caused by: java.net.ConnectException: Connection refused: connect
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:295)
        at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:161)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:148)
        at java.net.Socket.connect(Socket.java:425)
        at java.net.Socket.connect(Socket.java:375)
        at java.net.Socket.(Socket.java:290)
        at java.net.Socket.(Socket.java:118)
        at org.seasar.system.RMIConnector.getRMIAdaptorBySocket(RMIConnector.java:74)
        at org.seasar.system.RMIConnector.getRMIAdaptor(RMIConnector.java:41)
        at org.seasar.system.MBeanProxy.invoke(MBeanProxy.java:100)
        at $Proxy0.lookup(Unknown Source)
        at org.seasar.naming.NamingServerWrapper.lookup(NamingServerWrapper.java:42)
    	... 4 more

Seasarを開始させた後にプログラムを実行しましょう。
下記のような結果になるはずです。

    SMITH
    ALLEN
    WARD
    JONES
    MARTIN
    BLAKE
    CLARK
    SCOTT
    KING
    TURNER
    ADAMS
    JAMES
    FORD
    MILLER

## トランザクション処理

トランザクションも、JNDI経由(InitialContext)で、
javax.transaction.UserTransactionを取得して処理します。
Connectionのcommit,rollbackを使うよりも、JDBCの処理とトランザクション処理を
明確に分離できます。
トランザクションのために、複数のメソッドで、Connectionを持ちまわるような必要もなくなります。
InitialContextを取得する部分は、DataSourceの場合と同様です。
lookup()で指定するJNDI名は、java:comp/UserTransactionになります。

トランザクションは、UserTransaction#begin()で開始します。
トランザクションをコミットしたい場合は、UserTransaction#commit()を呼び出します。
トランザクションをロールバックしたい場合は、UserTransaction#rollback()を呼び出します。

#### examples.org.seasar.TransactionExample

    package examples.org.seasar;

    import java.sql.Connection;
    import java.sql.Statement;
    import java.util.Properties;

    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.sql.DataSource;
    import javax.transaction.UserTransaction;

    public class TransactionExample {

        private static final String FACTORY =
            "org.seasar.naming.NamingContextFactory";
        private static final String URL = "localhost:1108";
        private static final String TX_JNDI_NAME = "java:comp/UserTransaction";
        private static final String DS_JNDI_NAME = "jdbc/hsqldb";
        private static final String SQL =
            "UPDATE emp SET ename='SCOTT' WHERE empno = 7788";

        public static void main(String[] args) {
            try {
                Properties env = new Properties();
                env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
                env.put(Context.PROVIDER_URL, URL);
                InitialContext ctx = new InitialContext(env);
                UserTransaction tx = (UserTransaction) ctx.lookup(TX_JNDI_NAME);
                DataSource ds = (DataSource) ctx.lookup(DS_JNDI_NAME);
                Connection con = null;
                Statement stmt = null;
                tx.begin();
                try {
                    con = ds.getConnection();
                    stmt = con.createStatement();
                    int rows = stmt.executeUpdate(SQL);
                    System.out.println("updated " + rows + " row(s)");
                    tx.commit();
                } catch (Exception ex) {
                    tx.rollback();
                    ex.printStackTrace();
                } finally {
                    if (stmt != null) {
                        stmt.close();
                    }
                    if (con != null) {
                        con.close();
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

実行結果は下記のようになります。

    DEBUG 2003-09-15 21:01:32,299 [main] Transaction.begin()
    updated 1 row(s)
    DEBUG 2003-09-15 21:01:32,489 [main] Transaction.commit()

## Tomcatの利用

Webのコンテナには、使い慣れたTomcatを使い、コネクションプールや
トランザクション機能は、Seassarを使うといったこともできます。
この場合、Seasarはサーブレットとして実行します。
そのためには、WEB-INF/web.xmlに次の記述を追加します。

    <servlet>
        <servlet-name>seasar</servlet-name>
        <servlet-class>org.seasar.system.SeasarServlet</servlet-class>
        <load-on-startup/>
    </servlet>

また、WEB-INF/classes/seasar-config.xmlを次のように記述します。

    <seasar>
        <services>
            <service className="org.seasar.system.JMXService"/>
            <service className="org.seasar.system.RMIAdaptorService">
                <properties>
                    <property name="port" value="1108"/>
                </properties>
            </service>
            <service className="org.seasar.naming.NamingService"/>
            <service className="org.seasar.transaction.TransactionService"/>
            <service className="org.seasar.sql.ConnectionPoolService"/>
        </services>
    </seasar>

後は、WEB-INF/classesに$SEASAR_HOME/classes/connectionpool-config.xmlをコピーして
適当に編集します。
これらの設定の雛型が、$SEASAR_HOME/tomnekoに用意されているので、
それを使ってください。

## Seasarサービス

Seasarは、プラグイン型のアーキテクチャを採用していて、JNDI、JTA、コネクションプールなどの
サービスも実は、Seasarサービスとして組み込まれています。
$SEASAR_HOME/classes/seasar-config.xmlをみると現在組み込まれているサービスを
確認できます。

#### seasar-config.xml

    <seasar>
      <services>
        <service className="org.seasar.system.JMXService"/>
        <service className="org.seasar.system.RMIAdaptorService">
          <properties>
            <property name="port" value="1108"/>
          </properties>
        </service>
        <service className="org.seasar.naming.NamingService"/>
        <service className="org.seasar.transaction.TransactionService"/>
        <service className="org.seasar.sql.ConnectionPoolService"/>
        <service className="org.seasar.mbean.MBeanService"/>
      </services>
    </seasar>

JMXServiceは、Seasarの中核となるサービスで、JMXの機能を提供しています。

RMIAdaptorServiceは、JMXServiceをRMI経由で利用するためのアダプタ機能を提供しています。
この例のように、プロパティに値を設定することもできます。
RMIAdaptorServiceには、getPort(),setPort()のメソッドが定義されているため、
Seasarは、portをプロパティとして認識できます。プロパティがプリミティブ型の場合、
文字列からプリミティブ型への変換は自動的に行われます。
SeasarContextの説明で java.naming.provider.urlにlocalhost:1108を
指定していたかと思いますが、この1108はRMIAdaptorServiceのポート番号をあわせる必要があります。

NamingServiceは、JNDIの機能を提供しています。

TransactionServiceは、JTA(トランザクション)の機能を提供しています。

ConnectionPoolServiceは、コネクションプールの機能を提供しています。

MBeanServiceは、MBeanをサービスとしてSeasarに組み込む機能を提供しています。
MBeanについては、MBeanサービスで説明します。

Seasarサービスを提供するためには、org.seasar.system.Lifecycleインターフェースを
実装したクラスをseasar-config.xmlのclassNameに記述するだけなので簡単です。
上記の例のように、サービスのインスタンスのプロパティを設定することもできます。

#### org.seasar.system.Lifecycle

    import org.seasar.util.SeasarException;

    public interface Lifecycle {

        public void start() throws SeasarException;

        public void stop() throws SeasarException;
    }

Seasarの起動時に、seasar-config.xmlに登録されている順番で、各サービスの
start()が呼び出されます。
Seasarの終了時には、seasar-config.xmlに登録されている逆の順番で、各サービスの
stop()が呼び出されます。