失敗
Tomcat のコネクションプーリングを使用するために、DB 接続情報を定義した context.xml を作成し、META-INF ディレクトリに配置しました。 ところが、Web アプリをデプロイしてみると NullPointerException が発生してしまいます (スタックトレース) 。
jdbc.dicon などの設定も終わっているはずなのに、いったい何が問題なのでしょうか?
環境
このレポートは、以下の環境について記述したものです。
| JDK | Java SE Development Kit 6 Update 16 |
| AP サーバ | Tomcat 6.20 |
| Seasar |
|
| Dolteng プラグイン | Dolteng 0.39 |
| DBMS | MySQL 5.1 |
| JDBC | Connector/J 5.1.10 |
スタックトレース
- S2JDBC-Gen 実行時のスタックトレース
原因
原因は context.xml の配置場所を誤るという、恥ずかしいものでした。
○ ・・・ <プロジェクト・ルート>/src/main/webapp/META-INF/context.xml
× ・・・ <プロジェクト・ルート>/src/main/resources/META-INF/context.xml
解決策
Tomcat のコネクションプーリングを使用するための設定手順を示します。
(1) context.xml の作成
<プロジェクト・ルート>/src/main/webapp/META-INF ディレクトリに context.xml を作成します。 内容は DB への接続情報です。
<Context> <WatchedResource>WEB-INF/web.xml</WatchedResource> <Resource name="jdbc/my_ds" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" username="root" password="password" url="jdbc:mysql://127.0.0.1:3306/mydb" auth="Container" maxActive="25" maxIdle="4" maxWait="10000" /> </Context>
Resource 要素の属性を下表に示します。
| 属性 | 説明 |
|---|---|
| name | JNDI リソース名 (任意) |
| type | リソースのクラス or インターフェイス名 |
| driverClassName | JDBC ドライバのクラス名 |
| username | DB のユーザ名 |
| password | DB のパスワード |
| url | DB の接続 URL |
| auth |
Application ・・・ アプリケーション管理 Container ・・・ コンテナ管理 |
| maxActive | DB 接続の最大接続数。0 で無限大。 |
| maxIdle | アイドル状態の接続の最大数。0 で無限大。 |
| maxWait | プールに利用可能な接続がない場合に、利用可能な接続ができるまで待つ時間 (ミリ秒単位) 。-1 で無制限。 |
(2) web.xml の編集
web.xml に resource-ref 要素を追加し、context.xml で定義したデータソースへの参照ルックアップ名を追加します。 子要素の res-ref-name 要素には、(1) の name に指定した JNDI リソース名を指定します。 これにより、java:comp/env/ からの相対パスで参照できるようになります。
<?xml version="1.0"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <!-- 省略 --> <resource-ref> <res-ref-name>jdbc/my_ds</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app>
(3) jdbc.dicon の編集
jdbc.dicon には、JDBC データソースを定義します。 (1) ~ (2) で定義したデータソースを使用するように変更すれば、Tomcat のコネクションプーリングを使用できます。
ただ、このファイルを直接変更すると、常に Tomcat からデータソースを取得するようになり、S2JDBC-Gen が動作しなくなります。 この問題を避けるため、jdbc.dicon にデータソースを定義せず、環境定義 (env.txt の値) に応じて別の設定ファイルを読み込むようにします。
- env.txt が product の場合
- jdbc_product.dicon を読み込み、Tomcat のコネクションプーリングを使用します。
- env.txt が product 以外の場合
- jdbc_ut.dicon を読み込み、S2DBCP を使用します。
<?xml version="1.0"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components> <include condition="#ENV == 'product'" path="jdbc_product.dicon"/> <include condition="#ENV != 'product'" path="jdbc_ut.dicon"/> </components>
(4) jdbc_product.dicon の作成
Tomcat のコネクションプールからデータソースを取得します。 JndiResourceLocator@lookup に web.xml で設定した参照ルックアップ名を指定します (本例では java:comp/env/jdbc/my_ds) 。
<?xml version="1.0"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components namespace="jdbc">
<include path="jta.dicon"/>
<include path="jdbc-extension.dicon"/>
<component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
<component class="org.seasar.extension.jdbc.impl.ConfigurableStatementFactory">
<arg>
<component class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>
</arg>
<property name="fetchSize">100</property>
<!--
<property name="maxRows">100</property>
-->
</component>
<component name="DataSource"
class="javax.sql.DataSource">
@org.seasar.extension.j2ee.JndiResourceLocator@lookup("java:comp/env/jdbc/my_ds")
</component>
</components>
(5) jdbc_ut.dicon の作成
S2DBCP を使用して、データソースを取得します。 driverClassName、URL、user、password を環境に合わせて、変更してください。
<?xml version="1.0"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components> <include path="jta.dicon"/> <component name="xaDataSource" class="org.seasar.extension.dbcp.impl.XADataSourceImpl"> <property name="driverClassName"> "com.mysql.jdbc.Driver" </property> <property name="URL"> "jdbc:mysql://localhost:3306/mydb" </property> <property name="user">"root"</property> <property name="password">"password"</property> </component> <component name="connectionPool" class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl"> <property name="timeout">600</property> <property name="maxPoolSize">10</property> <property name="allowLocalTx">true</property> <destroyMethod name="close"/> </component> <component name="DataSource" class="org.seasar.extension.dbcp.impl.DataSourceImpl"/> </components>
(6) Connector/J の配置
最後に JDBC ドライバを配置します。 本稿では MySQL 用の Connector/J (mysql-connector-java-5.1.10-bin.jar) を使用します。
- Tomcat 用
- <CATALINA_HOME>/lib ディレクトリに配置します。
- S2DBCP 用
- <プロジェクト・ルート>/src/main/webapp/WEB-INF/lib ディレクトリに配置します。
以上で設定は完了です。 env.txt を product にすれば、Tomcat のコネクションプーリングを使用するようになります。
補足
■ S2JDBC-Gen の環境定義
S2JDBC-Gen が実行される環境は env パラメータで指定できます。 Dolteng でプロジェクトを作成した場合は、デフォルトで ut になっています。
<project name="mysample-s2jdbc-gen" default="gen-ddl" basedir="."> <!-- 省略 --> <property name="env" value="ut"/> <!-- 省略 --> <project>
