●JNDIとデータベース・リソース
JNDI(Java Naming and Directory Interface)とは、
Javaアプリケーションにおいて、リソースにつけられた名前から、
それが指すリソースを特定し、アクセスできるようにする「名前解決」の仕組みです。
ここでいうリソースとは、Javaアプリケーションが利用する情報源で、
自分自身以外に由来するものです。
業務アプリケーションで必要となる代表的にリソースは2つあり、
事例、サンプルでもしばしばとりあげられます。
ひとつはJavaMail APIを使って電子メールを送信する際のメールサーバ
(SMTPホスト)を特定する情報(javax.mail.Session)、
そしてもうひとつは皆さんよくご存知のデータベースを特定する情報(javax.sql.DataSource)です。
ここではまず、JNDIを使ってデータベースをリソースとしてアクセスする方法について、
簡単にメモっています。
サーブレットコンテナに載っているアプリケーションで、
あるデータベースにJNDI経由でアクセスできるようにする手順は、次の通りです。
- サーブレットコンテナのシステム設定ファイル
(Jakarta Tomcatならserver.xml、BXSならsystem.xmlなどなど)
に、リソースの名前とそれが指すデータベース・リスナーへの接続情報を書く。
- Webアプリケーションの設定ファイル(web.xml)で、
サーブレットなどがアクセスするリソースの名前とそのデータ型
(Javaクラス名)を書く。
- 実際に、JNDIでリソースにアクセスするアプリケーションを開発する。
●サーブレットコンテナの設定
サーブレットコンテナ側の設定はコンテナによって異なります。
ここではJakarta Tomcat 4.1.x〜5.0.xの設定ファイル($CATALINA_HOME/conf/server.xml)
の記述例を紹介します。
<Context path="/app01" docBase="C:/usr/javadeploy/app01" debug="0" reloadable="true">
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="app01." suffix=".txt" timestamp="true"/>
<Resource name="jdbc/mudb" auth="Container" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/mudb">
<parameter><name>username</name><value>urano</value></parameter>
<parameter><name>password</name><value>urano398</value></parameter>
<parameter><name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value></parameter>
<parameter><name>url</name>
<value>jdbc:mysql://localhost/udb?useUnicode=true&characterEncoding=SJIS</value></parameter>
</ResourceParams>
</Context>
|
(※注:url属性の値の中に、&という文字がありますが、
これはXMLファイルでは&(←Webブラウザで見えているまま)と書きます)
このように、利用したいアプリケーションコンテキスト(ここでは/app01)
の中で、ResourceタグとResourceParams
タグを対にして記述します。
リソースの名前は、データベース・リソースの場合「jdbc」を冠するのが慣習で、
ここでは「jdbc/mudb」としています。
ResourceParamsタグの中には、実際にそのデータベースに接続するために必要な情報を記述します。
これはどのデータベースでも共通で、上の例で大体網羅していると思います。
(注:「username」「url」は以前のバージョンではそれぞれ
「user」「driverName」とされていました。
そのため、書籍によってこちらの記述を使われている場合もあります。
Tomcatでは、ドキュメントには「後方互換性のために残されている」と書かれていますが、
実際に新しいバージョンのTomcatでuserやdriverNameを使うと既に認識されなくなっています。)
com.mysql.jdbc.Driver はMySQL ABが配布している、MySQL用のJDBCドライバの名前で、
他のデータベースの場合はそれに合わせたものを入手し、それを指定します。
なお、これはcom.mysql.jdbc.Driverだけの事情ですが、
このJDBCドライバではURLに上記の?以下のオプションを指定しないと、
JDBCのResultSetMetaDataオブジェクトを使った列名の参照がうまくできません。
その場合にURLに&文字を含める必要がありますが、これは&とエスケープします。
●Webアプリケーションの設定
アプリケーションの設定はWEB-INF/web.xmlの中で次のように行います。
<resource-ref>
<res-ref-name>jdbc/udb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
|
アプリケーション側で設定する必要があるものはこれだけです。
つまるところ、
- このアプリケーションは「jdbc/udb」というリソースを使うのです。
- それはjavax.sql.DataSourceクラスのオブジェクトです。
これだけのことをアプリケーションからコンテナに伝えておけば、
後はコンテナの方が実際のリソースとのやりとりを行ってくれます。
この最大の恩恵は、Webアプリケーションがコンテナの制約を受けない、
ということです。例えば、オープンソースのコンテナの元で開発を進め、
実際の運用にはロードバランサーなどを備えた市販のコンテナを使う、等のことが可能です。
●プログラムの中から
サーブレットなどのアプリケーション・プログラムの中では、
先述の通り、「これこれのリソースが必要です」と発すると、
コンテナが設定にもとづき適切なリソースを探して返してきます。
try {
Context c = new InitialContext();
DataSource ds = (DataSource) c.lookup(jndiName);
Connection conn = ds.getConnection();
} catch(NamingException ex){
throw new SQLException(
"cannot lookup database resource from jndi namespace: " + ex.toString());
}
}
|
リソースを探すメソッドはjavax.naming.Context.lookup
ですが、そのとき指定するのはリソースの名前ではなくJNDI名と呼ばれるものです。
サーブレットで使うJNDI名は、サーブレットの規約により、
「java:comp/env/リソース名」と決められています。
従ってこの例では、「java:comp/env/jdbc/udb」となります。
(first uploaded 2002/03/02 last updated 2004/07/25, KQ TAURA - URANO398)
|