JNDIリソース設定方法
目次
はじめに
Tomcatは、WebアプリケーションごとにJNDIのInitialContext実装インスタンスを提供します。これは、Jakarta EEアプリケーションサーバーが提供するものと互換性のある方法で行われます。Jakarta EE標準は、リソースを参照/定義するために、/WEB-INF/web.xml
ファイルに標準の要素セットを提供します。
JNDIのプログラミングAPI、およびTomcatが提供するサービスについてエミュレートするJakarta EEサーバーがサポートする機能の詳細については、以下の仕様を参照してください。
- Java Naming and Directory Interface (JDK 1.4以降に付属)
- Jakarta EE Platform Specification (特に、Namingに関する第5章を参照)
web.xml設定
Webアプリケーションにリソースを定義するには、Webアプリケーションデプロイメント記述子(/WEB-INF/web.xml
)で以下の要素を使用できます。
<env-entry>
- 環境エントリ。アプリケーションの動作を設定するために使用できる単一値パラメータです。<resource-ref>
- リソース参照。通常、JDBCDataSource
、Jakarta MailSession
、またはTomcatに設定されたカスタムオブジェクトファクトリなどのリソースのオブジェクトファクトリを指します。<resource-env-ref>
- リソース環境参照。Servlet 2.4で追加されたresource-ref
の新しいバリエーションで、認証情報を必要としないリソースに対してより簡単に設定できます。
Tomcatがリソースの作成に使用する適切なリソースファクトリを識別でき、それ以上の設定情報が必要ない場合、Tomcatは/WEB-INF/web.xml
の情報を使用してリソースを作成します。
Tomcatは、web.xmlで指定できないJNDIリソース用のTomcat固有のオプションをいくつか提供します。これには、Webアプリケーション停止時のJNDIリソースのクリーンアップを高速化するcloseMethod
と、JNDIルックアップごとにリソースの新しいインスタンスを作成するかどうかを制御するsingleton
が含まれます。これらの設定オプションを使用するには、リソースをWebアプリケーションの<Context>
要素または$CATALINA_BASE/conf/server.xml
の<GlobalNamingResources>
要素で指定する必要があります。
context.xml設定
Tomcatが適切なリソースファクトリを識別できない場合、および/または追加の設定情報が必要な場合、Tomcatがリソースを作成する前に、追加のTomcat固有の設定を指定する必要があります。Tomcat固有のリソース設定は、$CATALINA_BASE/conf/server.xml
または、WebアプリケーションごとのコンテキストXMLファイル(META-INF/context.xml
)のいずれかで指定できる<Context>
要素に入力します。
Tomcat固有のリソース設定は、<Context>
要素内の以下の要素を使用して行われます。
- <Environment> - JNDI
InitialContext
を通じてWebアプリケーションに公開されるスカラー環境エントリの名前と値を設定します(Webアプリケーションデプロイメント記述子に<env-entry>
要素を含めることと同等です)。 - <Resource> - アプリケーションに提供されるリソースの名前とデータ型を設定します(Webアプリケーションデプロイメント記述子に
<resource-ref>
要素を含めることと同等です)。 - <ResourceLink> - グローバルJNDIコンテキストで定義されたリソースへのリンクを追加します。リソースリンクを使用して、Webアプリケーションが<Server>要素の<GlobalNamingResources>子要素で定義されたリソースにアクセスできるようにします。
- <Transaction> -
java:comp/UserTransaction
で利用可能なUserTransactionオブジェクトインスタンスをインスタンス化するためのリソースファクトリを追加します。
これらの要素は、<Context>
要素内にいくつでもネストでき、その特定のWebアプリケーションのみに関連付けられます。
<Context>
要素でリソースが定義されている場合、そのリソースを/WEB-INF/web.xml
で定義する必要はありません。ただし、Webアプリケーションのリソース要件を文書化するために、/WEB-INF/web.xml
にエントリを保持することをお勧めします。
Webアプリケーションデプロイメント記述子 (/WEB-INF/web.xml
) に含まれる<env-entry>
要素と、Webアプリケーションの<Context>
要素の一部である<Environment>
要素で同じリソース名が定義されている場合、デプロイメント記述子の値は、対応する<Environment>
要素で許可されている場合 (override
属性を"true"に設定することで) のみ優先されます。
グローバル設定
Tomcatは、サーバー全体のグローバルリソースの別個のネームスペースを管理しています。これらは、$CATALINA_BASE/conf/server.xml
の<GlobalNamingResources>
要素で設定されます。<ResourceLink>を使用してWebアプリケーションごとのコンテキストに含めることで、これらのリソースをWebアプリケーションに公開できます。
<ResourceLink>を使用してリソースが定義されている場合、そのリソースを/WEB-INF/web.xml
で定義する必要はありません。ただし、Webアプリケーションのリソース要件を文書化するために、/WEB-INF/web.xml
にエントリを保持することをお勧めします。
リソースの利用
InitialContext
は、Webアプリケーションが最初にデプロイされる際に設定され、Webアプリケーションコンポーネントに(読み取り専用アクセスで)利用可能になります。すべての設定されたエントリとリソースは、JNDIネームスペースのjava:comp/env
部分に配置されるため、リソース(この場合はJDBC DataSource
)への典型的なアクセスは次のようになります。
// Obtain our environment naming context
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
// Look up our data source
DataSource ds = (DataSource)
envCtx.lookup("jdbc/EmployeeDB");
// Allocate and use a connection from the pool
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();
Tomcat標準リソースファクトリ
Tomcatには、Webアプリケーションにサービスを提供できる一連の標準リソースファクトリが含まれており、Webアプリケーションやデプロイメント記述子を変更することなく(<Context>
要素を介して)設定の柔軟性を提供します。以下の各サブセクションでは、標準リソースファクトリの設定と使用法について詳しく説明します。
Tomcatで独自のカスタムリソースファクトリクラスを作成、インストール、設定、使用する方法については、「カスタムリソースファクトリの追加」を参照してください。
注 - 標準リソースファクトリのうち、「JDBCデータソース」と「ユーザートランザクション」ファクトリのみが他のプラットフォームで利用可能であることが義務付けられており、それらもプラットフォームがJakarta EE仕様を実装している場合にのみ必要です。その他のすべての標準リソースファクトリと、自分で作成するカスタムリソースファクトリはTomcat固有のものであり、他のコンテナで利用できるとは限りません。
汎用JavaBeanリソース
0. はじめに
このリソースファクトリは、標準のJavaBean命名規約(つまり、引数なしのコンストラクタを持ち、setFoo()命名パターンに準拠するプロパティセッターを持つ)に準拠する任意のJavaクラスのオブジェクトを作成するために使用できます。ファクトリのsingleton
属性がfalse
に設定されている場合、このエントリのlookup()
が実行されるたびに、リソースファクトリは適切なBeanクラスの新しいインスタンスを作成します。
この機能を使用するために必要な手順を以下に示します。
1. JavaBeanクラスを作成する
リソースファクトリがルックアップされるたびにインスタンス化されるJavaBeanクラスを作成します。この例では、以下のようなcom.mycompany.MyBean
クラスを作成すると仮定します。
package com.mycompany;
public class MyBean {
private String foo = "Default Foo";
public String getFoo() {
return (this.foo);
}
public void setFoo(String foo) {
this.foo = foo;
}
private int bar = 0;
public int getBar() {
return (this.bar);
}
public void setBar(int bar) {
this.bar = bar;
}
}
2. リソース要件を宣言する
次に、Webアプリケーションデプロイメント記述子(/WEB-INF/web.xml
)を変更して、このBeanの新しいインスタンスを要求するJNDI名を宣言します。最も簡単な方法は、次のように<resource-env-ref>
要素を使用することです。
<resource-env-ref>
<description>
Object factory for MyBean instances.
</description>
<resource-env-ref-name>
bean/MyBeanFactory
</resource-env-ref-name>
<resource-env-ref-type>
com.mycompany.MyBean
</resource-env-ref-type>
</resource-env-ref>
警告 - Webアプリケーションデプロイメント記述子のDTDで要求される要素の順序を必ず守ってください!詳細については、サーブレット仕様を参照してください。
3. アプリケーションでこのリソースを使用するコードを記述する
このリソース環境参照の典型的な使用例は次のようになります。
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory");
writer.println("foo = " + bean.getFoo() + ", bar = " +
bean.getBar());
4. Tomcatのリソースファクトリを設定する
Tomcatのリソースファクトリを設定するには、このWebアプリケーションの<Context>
要素に、次のような要素を追加します。
<Context ...>
...
<Resource name="bean/MyBeanFactory" auth="Container"
type="com.mycompany.MyBean"
factory="org.apache.naming.factory.BeanFactory"
bar="23"/>
...
</Context>
リソース名(ここではbean/MyBeanFactory
)がWebアプリケーションデプロイメント記述子で指定された値と一致する必要があることに注意してください。また、bar
プロパティの値も初期化しており、これにより新しいBeanが返される前にsetBar(23)
が呼び出されます。foo
プロパティは初期化していませんが(初期化することもできます)、Beanにはコンストラクタによって設定されたデフォルト値が含まれます。
BeanプロパティがString
型の場合、BeanFactoryは提供されたプロパティ値を使用してプロパティセッターを呼び出します。Beanプロパティがプリミティブ型またはプリミティブラッパー型の場合、BeanFactoryは値を適切なプリミティブ型またはプリミティブラッパー型に変換し、その値をセッターを呼び出すときに使用します。一部のBeanには、String
から自動的に変換できない型のプロパティがあります。Beanが同じ名前でString
を受け取る代替セッターを提供する場合、BeanFactoryはそのセッターを使用しようとします。BeanFactoryが値を使用できないか、適切な変換を実行できない場合、プロパティの設定はNamingExceptionで失敗します。
以前のTomcatリリースで利用可能だったforceString
プロパティは、セキュリティ強化策として削除されました。
メモリUserDatabaseリソース
0. はじめに
UserDatabaseリソースは通常、UserDatabaseレルムで使用するためのグローバルリソースとして設定されます。Tomcatには、XMLファイル(通常はtomcat-users.xml
)によってバックアップされるUserDatabaseリソースを作成するUserDatabaseFactoryが含まれています。
グローバルUserDatabaseリソースを設定するために必要な手順を以下に示します。
1. XMLファイルを作成/編集する
XMLファイルは通常、$CATALINA_BASE/conf/tomcat-users.xml
に配置されますが、ファイルシステム上の任意の場所に配置できます。XMLファイルは$CATALINA_BASE/conf
に配置することをお勧めします。典型的なXMLは次のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>
2. リソースを宣言する
次に、$CATALINA_BASE/conf/server.xml
を修正して、XMLファイルに基づいてUserDatabaseリソースを作成します。次のような記述になります。
<Resource name="UserDatabase"
auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml"
readonly="false" />
pathname
属性は、URL、絶対パス、または相対パスにすることができます。相対パスの場合、$CATALINA_BASE
からの相対パスになります。
readonly
属性はオプションであり、指定されない場合はデフォルトでtrue
になります。XMLが書き込み可能である場合、Tomcatの起動時に書き込まれます。警告:ファイルが書き込まれると、Tomcatが実行されているユーザーのデフォルトのファイルパーミッションを継承します。インストールのセキュリティを維持するために、これらが適切であることを確認してください。
レルム内で参照される場合、UserDatabaseはデフォルトでpathname
の変更を監視し、最終変更時刻の変更が検出された場合はファイルを再ロードします。これは、watchSource
属性をfalse
に設定することで無効にできます。
3. レルムを設定する
レルム設定ドキュメントに記載されているように、UserDatabaseレルムを設定してこのリソースを使用します。
DataSource UserDatabaseリソース
0. はじめに
Tomcatには、バックエンドとしてDataSource
リソースを使用するUserDatabase
も含まれています。バックエンドリソースは、それを使用するユーザーデータベースと同じJNDIコンテキストで宣言する必要があります。
グローバルUserDatabaseリソースを設定するために必要な手順を以下に示します。
1. データベーススキーマ
ユーザーデータベースのデータベーススキーマは柔軟です。これは、DataSourceRealm
で使用されるスキーマと同じで、ユーザー(ユーザー名、パスワード)のテーブルと、各ユーザーに関連付けられたロールを一覧表示する別のテーブルのみで構成することもできます。UserDatabase
の全機能をサポートするには、グループ用の追加のテーブルを含める必要があり、ユーザー、グループ、ロール間の参照整合性と互換性があります。
グループと参照整合性を備えた全機能スキーマは次のとおりです。
create table users (
user_name varchar(32) not null primary key,
user_pass varchar(64) not null,
user_fullname varchar(128)
-- Add more attributes as needed
);
create table roles (
role_name varchar(32) not null primary key,
role_description varchar(128)
);
create table groups (
group_name varchar(32) not null primary key,
group_description varchar(128)
);
create table user_roles (
user_name varchar(32) references users(user_name),
role_name varchar(32) references roles(role_name),
primary key (user_name, role_name)
);
create table user_groups (
user_name varchar(32) references users(user_name),
group_name varchar(32) references groups(group_name),
primary key (user_name, group_name)
);
create table group_roles (
group_name varchar(32) references groups(group_name),
role_name varchar(32) references roles(role_name),
primary key (group_name, role_name)
);
グループを使用できない最小限のスキーマは(DataSourceRealm
の場合と同じです)次のようになります。
create table users (
user_name varchar(32) not null primary key,
user_pass varchar(64) not null,
-- Add more attributes as needed
);
create table user_roles (
user_name varchar(32),
role_name varchar(32),
primary key (user_name, role_name)
);
2. リソースを宣言する
次に、$CATALINA_BASE/conf/server.xml
を修正して、DataSource
とそのスキーマに基づいてUserDatabaseリソースを作成します。次のような記述になります。
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.DataSourceUserDatabaseFactory"
dataSourceName="jdbc/authority" readonly="false"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name"
roleTable="roles" groupTable="groups" userGroupTable="user_groups"
groupRoleTable="group_roles" groupNameCol="group_name" />
dataSourceName
属性は、UserDatabase
のバックエンドとなるDataSource
のJNDI名です。これは、UserDatabase
と同じJNDI Context
で宣言する必要があります。詳細な手順については、DataSource
リソースのドキュメントを参照してください。
readonly
属性はオプションで、指定しない場合はデフォルトでtrue
になります。データベースが書き込み可能であれば、Tomcat管理を介してUserDatabase
に加えられた変更は、save
操作を使用してデータベースに永続化できます。
あるいは、バックエンドデータベースに直接変更を加えることもできます。
3. リソース設定
属性 | 説明 |
---|---|
dataSourceName |
このUserDatabaseのJNDI JDBC DataSourceの名前。 |
groupNameCol |
"groups"、"group roles"、"user groups"テーブル内の、グループ名を含むカラムの名前。 |
groupRoleTable |
|
groupTable |
|
readonly |
これが |
roleAndGroupDescriptionCol |
"roles"および"groups"テーブル内の、ロールとグループの説明を含むカラムの名前。 |
roleNameCol |
"roles"、"user roles"、"group roles"テーブル内の、対応するユーザーに割り当てられたロール名を含むカラムの名前。 この属性は、ほとんどの設定で必須です。省略可能な稀なケースについては、関連するレルムのallRolesMode属性を参照してください。 |
roleTable |
|
userCredCol |
"users"テーブル内の、ユーザーの資格情報(つまりパスワード)を含むカラムの名前。 |
userGroupTable |
|
userNameCol |
"users"、"user groups"、"user roles"テーブル内の、ユーザー名を含むカラムの名前。 |
userFullNameCol |
"users"テーブル内の、ユーザーのフルネームを含むカラムの名前。 |
userRoleTable |
この属性は、ほとんどの設定で必須です。省略可能な稀なケースについては、関連するレルムのallRolesMode属性を参照してください。 |
userTable |
|
4. レルムを設定する
レルム設定ドキュメントに記載されているように、UserDatabaseレルムを設定してこのリソースを使用します。
Jakarta Mailセッション
0. はじめに
多くのWebアプリケーションでは、電子メールメッセージの送信はシステム機能の必須部分です。Jakarta Mail APIは、このプロセスを比較的簡単にしますが、クライアントアプリケーションが認識している必要がある多くの設定詳細(メッセージ送信に使用するSMTPホストの名前を含む)を必要とします。
Tomcatには、あらかじめSMTPサーバーに接続するように設定されたjakarta.mail.Session
セッションインスタンスを作成する標準リソースファクトリが含まれています。このようにして、アプリケーションはメールサーバー設定環境の変更から完全に隔離されます。アプリケーションは、必要に応じて事前設定されたセッションを要求し、受け取るだけです。
これに必要な手順を以下に示します。
1. リソース要件を宣言する
まず、Webアプリケーションデプロイメント記述子(/WEB-INF/web.xml
)を変更して、事前設定されたセッションをルックアップするJNDI名を宣言します。慣例により、そのようなすべての名前は、提供されるすべてのリソースファクトリのルートである標準のjava:comp/env
命名コンテキストに対するmail
サブコンテキストに解決されるべきです。典型的なweb.xml
エントリは次のようになります。
<resource-ref>
<description>
Resource reference to a factory for jakarta.mail.Session
instances that may be used for sending electronic mail
messages, preconfigured to connect to the appropriate
SMTP server.
</description>
<res-ref-name>
mail/Session
</res-ref-name>
<res-type>
jakarta.mail.Session
</res-type>
<res-auth>
Container
</res-auth>
</resource-ref>
警告 - Webアプリケーションデプロイメント記述子のDTDで要求される要素の順序を必ず守ってください!詳細については、サーブレット仕様を参照してください。
2. アプリケーションでこのリソースを使用するコードを記述する
このリソース参照の典型的な使用例は次のようになります。
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
Session session = (Session) envCtx.lookup("mail/Session");
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(request.getParameter("from")));
InternetAddress to[] = new InternetAddress[1];
to[0] = new InternetAddress(request.getParameter("to"));
message.setRecipients(Message.RecipientType.TO, to);
message.setSubject(request.getParameter("subject"));
message.setContent(request.getParameter("content"), "text/plain");
Transport.send(message);
アプリケーションがWebアプリケーションデプロイメント記述子で宣言されたものと同じリソース参照名を使用していることに注意してください。これは、以下で説明するように、Webアプリケーションの<Context>
要素で構成されたリソースファクトリと照合されます。
3. Tomcatのリソースファクトリを設定する
Tomcatのリソースファクトリを設定するには、このWebアプリケーションの<Context>
要素に、次のような要素を追加します。
<Context ...>
...
<Resource name="mail/Session" auth="Container"
type="jakarta.mail.Session"
mail.smtp.host="localhost"/>
...
</Context>
リソース名(ここではmail/Session
)がWebアプリケーションデプロイメント記述子で指定された値と一致する必要があることに注意してください。mail.smtp.host
パラメーターの値を、ネットワーク上のSMTPサービスを提供するサーバーを指すようにカスタマイズしてください。
追加のリソース属性と値は、プロパティと値に変換され、java.util.Properties
コレクションの一部としてjakarta.mail.Session.getInstance(java.util.Properties)
に渡されます。Jakarta Mail仕様の付録Aで定義されているプロパティに加えて、個々のプロバイダも追加のプロパティをサポートする場合があります。
リソースがpassword
属性、およびmail.smtp.user
またはmail.user
属性のいずれかで設定されている場合、Tomcatのリソースファクトリはjakarta.mail.Authenticator
を構成し、メールセッションに追加します。
4. Jakarta Mail APIをインストールする
ディストリビューションを展開し、jakarta.mail-api-2.1.0.jar
を$CATALINA_HOME/lib
に配置して、メールセッションリソースの初期化中にTomcatが利用できるようにします。注: このJARを$CATALINA_HOME/lib
とWebアプリケーションのlibフォルダの両方に配置するとエラーが発生するため、$CATALINA_HOME/lib
の場所のみに配置されていることを確認してください。
5. 互換性のある実装をインストールする
互換性のある実装を選択してダウンロードします。
実装を展開し、JARファイルを$CATALINA_HOME/lib
に配置します。
注意:他の実装も利用できる場合があります。
6. Tomcatを再起動する
追加のJARをTomcatに認識させるためには、Tomcatインスタンスを再起動する必要があります。
アプリケーション例
Tomcatに同梱されている/examples
アプリケーションには、このリソースファクトリを利用する例が含まれています。「JSP Examples」リンクからアクセスできます。実際にメールメッセージを送信するサーブレットのソースコードは、/WEB-INF/classes/SendMailServlet.java
にあります。
警告 - デフォルトの設定では、localhost
のポート25でSMTPサーバーが待機していると想定しています。そうでない場合は、このWebアプリケーションの<Context>
要素を編集し、mail.smtp.host
パラメータの値をネットワーク上のSMTPサーバーのホスト名に変更してください。
JDBCデータソース
0. はじめに
多くのWebアプリケーションは、そのアプリケーションに必要な機能をサポートするために、JDBCドライバを介してデータベースにアクセスする必要があります。Jakarta EE Platform Specificationは、Jakarta EEアプリケーションサーバーがこの目的のためにDataSource実装(つまり、JDBC接続用の接続プール)を提供することを要求しています。Tomcatはまったく同じサポートを提供するため、このサービスを使用してTomcat上で開発するデータベースベースのアプリケーションは、どのJakarta EEサーバーでも変更なしで実行できます。
JDBCに関する情報については、以下を参照してください。
- http://www.oracle.com/technetwork/java/javase/jdbc/index.html - Java Database Connectivityに関する情報を提供しているホームページ。
- http://java.sun.com/j2se/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame.html - JDBC 2.1 API仕様。
- http://java.sun.com/products/jdbc/jdbc20.stdext.pdf - JDBC 2.0 Standard Extension API (
javax.sql.DataSource
APIを含む)。このパッケージは現在「JDBC Optional Package」として知られています。 - https://jakarta.ee/specifications/platform/9/ - Jakarta EEプラットフォーム仕様(すべてのJakarta EEプラットフォームがアプリケーションに提供しなければならないJDBC機能について記述)。
注 - Tomcatのデフォルトのデータソースサポートは、CommonsプロジェクトのDBCP 2コネクションプールに基づいています。ただし、以下で説明するように、独自のカスタムリソースファクトリを記述することで、javax.sql.DataSource
を実装する他の任意のコネクションプールを使用することも可能です。
1. JDBCドライバをインストールする
JDBCデータソースJNDIリソースファクトリを使用するには、適切なJDBCドライバをTomcat内部クラスとWebアプリケーションの両方で利用できるようにする必要があります。これは、ドライバのJARファイルを$CATALINA_HOME/lib
ディレクトリにインストールするのが最も簡単で、これによりドライバがリソースファクトリとアプリケーションの両方で利用可能になります。
2. リソース要件を宣言する
次に、Webアプリケーションデプロイメント記述子(/WEB-INF/web.xml
)を変更して、事前設定されたデータソースをルックアップするJNDI名を宣言します。慣例により、そのようなすべての名前は、提供されるすべてのリソースファクトリのルートである標準のjava:comp/env
命名コンテキストに対するjdbc
サブコンテキストに解決されるべきです。典型的なweb.xml
エントリは次のようになります。
<resource-ref>
<description>
Resource reference to a factory for java.sql.Connection
instances that may be used for talking to a particular
database that is configured in the <Context>
configuration for the web application.
</description>
<res-ref-name>
jdbc/EmployeeDB
</res-ref-name>
<res-type>
javax.sql.DataSource
</res-type>
<res-auth>
Container
</res-auth>
</resource-ref>
警告 - Webアプリケーションデプロイメント記述子のDTDで要求される要素の順序を必ず守ってください!詳細については、サーブレット仕様を参照してください。
3. アプリケーションでこのリソースを使用するコードを記述する
このリソース参照の典型的な使用例は次のようになります。
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource)
envCtx.lookup("jdbc/EmployeeDB");
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();
アプリケーションがWebアプリケーションデプロイメント記述子で宣言されたものと同じリソース参照名を使用していることに注意してください。これは、以下で説明するように、Webアプリケーションの<Context>
要素で構成されたリソースファクトリと照合されます。
4. Tomcatのリソースファクトリを設定する
Tomcatのリソースファクトリを設定するには、このWebアプリケーションの<Context>
要素に、次のような要素を追加します。
<Context ...>
...
<Resource name="jdbc/EmployeeDB"
auth="Container"
type="javax.sql.DataSource"
username="dbusername"
password="dbpassword"
driverClassName="org.hsql.jdbcDriver"
url="jdbc:HypersonicSQL:database"
maxTotal="8"
maxIdle="4"/>
...
</Context>
リソース名(ここではjdbc/EmployeeDB
)がWebアプリケーションデプロイメント記述子で指定された値と一致する必要があることに注意してください。
この例では、HypersonicSQLデータベースのJDBCドライバを使用していることを前提としています。実際のデータベースのJDBCドライバと接続URLに合わせて、driverClassName
およびdriverName
パラメータをカスタマイズしてください。
Tomcatの標準データソースリソースファクトリ (org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory
) の設定プロパティは以下のとおりです。
- driverClassName - 使用するJDBCドライバの完全修飾Javaクラス名。
- username - JDBCドライバに渡すデータベースユーザー名。
- password - JDBCドライバに渡すデータベースパスワード。
- url - JDBCドライバに渡す接続URL。(下位互換性のため、
driverName
プロパティも認識されます。) - initialSize - プール初期化時にプール内に作成される接続の初期数。デフォルト:0
- maxTotal - このプールから同時に割り当てることができる接続の最大数。デフォルト:8
- minIdle - このプールで同時にアイドル状態にある接続の最小数。デフォルト:0
- maxIdle - このプールで同時にアイドル状態にある接続の最大数。デフォルト:8
- maxWaitMillis - 接続が利用できない場合に、例外をスローする前にプールが接続が返されるのを待つ最大ミリ秒数。デフォルト:-1 (無限)
接続の検証を処理するいくつかの追加プロパティ
- validationQuery - アプリケーションに返される前に接続を検証するためにプールが使用できるSQLクエリ。指定された場合、このクエリは少なくとも1行を返すSQL SELECTステートメントでなければなりません。
- validationQueryTimeout - 検証クエリが返されるまでのタイムアウト(秒単位)。デフォルト:-1 (無限)
- testOnBorrow - trueまたはfalse:接続がプールから借りられるたびに、検証クエリを使用して検証されるべきかどうか。デフォルト:true
- testOnReturn - trueまたはfalse:接続がプールに返されるたびに、検証クエリを使用して検証されるべきかどうか。デフォルト:false
オプションのエビクター(強制削除)スレッドは、長時間アイドル状態の接続を削除することでプールを縮小する役割を担います。エビクターはminIdle
を尊重しません。設定されたmaxIdle
プロパティに従ってプールを縮小したいだけであれば、エビクターのスレッドをアクティブにする必要はありません。
エビクターはデフォルトで無効になっており、以下のプロパティを使用して設定できます。
- timeBetweenEvictionRunsMillis - エビクターの連続実行間のミリ秒数。デフォルト:-1 (無効)
- numTestsPerEvictionRun - エビクターの各実行中に、エビクターによってアイドル状態がチェックされる接続の数。デフォルト:3
- minEvictableIdleTimeMillis - 接続がエビクターによってプールから削除されるまでのアイドル時間(ミリ秒単位)。デフォルト:30*60*1000 (30分)
- testWhileIdle - trueまたはfalse:接続がプール内でアイドル状態の間に、エビクターのスレッドによって検証クエリを使用して検証されるべきかどうか。デフォルト:false
もう1つのオプション機能は、破棄された接続の削除です。接続は、アプリケーションが長時間プールに返さない場合に破棄されたと呼ばれます。プールは、そのような接続を自動的に閉じ、プールから削除できます。これは、接続リークが発生しているアプリケーションの回避策です。
破棄機能はデフォルトで無効になっており、以下のプロパティを使用して設定できます。
- removeAbandonedOnBorrow - trueまたはfalse:接続を借りるときに、破棄された接続をプールから削除するかどうか。デフォルト:false
- removeAbandonedOnMaintenance - trueまたはfalse:プールメンテナンス中に、破棄された接続をプールから削除するかどうか。デフォルト:false
- removeAbandonedTimeout - 借りられた接続が破棄されたとみなされるまでの秒数。デフォルト:300
- logAbandoned - trueまたはfalse:ステートメントまたは接続を破棄したアプリケーションコードのスタックトレースをログに記録するかどうか。これは深刻なオーバーヘッドを追加します。デフォルト:false
最後に、プールの動作をさらに細かく調整できるさまざまなプロパティがあります。
- defaultAutoCommit - trueまたはfalse:このプールによって作成される接続のデフォルトのオートコミット状態。デフォルト:true
- defaultReadOnly - trueまたはfalse:このプールによって作成される接続のデフォルトの読み取り専用状態。デフォルト:false
- defaultTransactionIsolation - デフォルトのトランザクション分離レベルを設定します。
NONE
、READ_COMMITTED
、READ_UNCOMMITTED
、REPEATABLE_READ
、SERIALIZABLE
のいずれかを指定できます。デフォルト:設定なし - poolPreparedStatements - trueまたはfalse:PreparedStatementsとCallableStatementsをプールするかどうか。デフォルト:false
- maxOpenPreparedStatements - ステートメントプールから同時に割り当てることができるオープンステートメントの最大数。デフォルト:-1 (無制限)
- defaultCatalog - デフォルトカタログの名前。デフォルト:設定なし
- connectionInitSqls - Connectionが作成された後に一度実行されるSQLステートメントのリスト。複数のステートメントはセミコロン(
;
)で区切ります。デフォルト:ステートメントなし - connectionProperties - 接続作成のためにドライバに渡されるドライバ固有のプロパティのリスト。各プロパティは
name=value
の形式で指定され、複数のプロパティはセミコロン(;
)で区切られます。デフォルト:プロパティなし - accessToUnderlyingConnectionAllowed - trueまたはfalse:基になる接続へのアクセスが許可されるかどうか。デフォルト:false
詳細については、Commons DBCP 2のドキュメントを参照してください。
カスタムリソースファクトリの追加
標準のリソースファクトリのいずれもニーズに合わない場合、独自のファクトリを記述してTomcatに統合し、Webアプリケーションの<Context>
要素でこのファクトリの使用を設定できます。以下の例では、上記の汎用JavaBeanリソースの例からcom.mycompany.MyBean
Beanを作成することのみを知っているファクトリを作成します。
1. リソースファクトリクラスを記述する
JNDIサービスプロバイダであるjavax.naming.spi.ObjectFactory
インターフェースを実装するクラスを記述する必要があります。Webアプリケーションがこのファクトリにバインドされているコンテキストエントリに対してlookup()
を呼び出すたび(ファクトリがsingleton="false"
で設定されていると仮定)、getObjectInstance()
メソッドが以下の引数で呼び出されます。
- Object obj - オブジェクトの作成に使用できる場所または参照情報を含む(nullの場合もある)オブジェクト。Tomcatの場合、これは常に
javax.naming.Reference
型のオブジェクトであり、このファクトリクラスのクラス名と、返されるオブジェクトの作成に使用する設定プロパティ(Webアプリケーションの<Context>
からのもの)が含まれます。 - Name name - このファクトリが
nameCtx
に相対的にバインドされている名前、または名前が指定されていない場合はnull
。 - Context nameCtx -
name
パラメータが相対的に指定されているコンテキスト、またはname
がデフォルトの初期コンテキストに相対的な場合はnull
。 - Hashtable environment - このオブジェクトの作成に使用される(nullの場合もある)環境。Tomcatオブジェクトファクトリでは、これは通常無視されます。
MyBean
インスタンスを生成する方法を知っているリソースファクトリを作成するには、次のようなクラスを作成できます。
package com.mycompany;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
public class MyBeanFactory implements ObjectFactory {
public Object getObjectInstance(Object obj,
Name name2, Context nameCtx, Hashtable environment)
throws NamingException {
// Acquire an instance of our specified bean class
MyBean bean = new MyBean();
// Customize the bean properties from our attributes
Reference ref = (Reference) obj;
Enumeration addrs = ref.getAll();
while (addrs.hasMoreElements()) {
RefAddr addr = (RefAddr) addrs.nextElement();
String name = addr.getType();
String value = (String) addr.getContent();
if (name.equals("foo")) {
bean.setFoo(value);
} else if (name.equals("bar")) {
try {
bean.setBar(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new NamingException("Invalid 'bar' value " + value);
}
}
}
// Return the customized instance
return (bean);
}
}
この例では、com.mycompany.MyBean
クラスの新しいインスタンスを無条件に作成し、このリソースを設定する<Resource>
要素に含まれるパラメータに基づいてそのプロパティを設定しています(以下を参照)。factory
という名前のパラメータはスキップする必要があることに注意してください。このパラメータは、設定対象のBeanのプロパティではなく、ファクトリクラス自体の名前(この場合、com.mycompany.MyBeanFactory
)を指定するために使用されます。
ObjectFactory
の詳細については、JNDIサービスプロバイダインターフェース(SPI)仕様を参照してください。
このクラスは、$CATALINA_HOME/lib
ディレクトリ内のすべてのJARファイルを含むクラスパスに対してコンパイルする必要があります。完了したら、ファクトリクラス(および対応するBeanクラス)を$CATALINA_HOME/lib
以下に展開するか、$CATALINA_HOME/lib
内のJARファイルに配置します。これにより、必要なクラスファイルがCatalina内部リソースとWebアプリケーションの両方から認識されます。
2. リソース要件を宣言する
次に、Webアプリケーションデプロイメント記述子(/WEB-INF/web.xml
)を変更して、このBeanの新しいインスタンスを要求するJNDI名を宣言します。最も簡単な方法は、次のように<resource-env-ref>
要素を使用することです。
<resource-env-ref>
<description>
Object factory for MyBean instances.
</description>
<resource-env-ref-name>
bean/MyBeanFactory
</resource-env-ref-name>
<resource-env-ref-type>
com.mycompany.MyBean
</resource-env-ref-type>
</resource-env-ref>
警告 - Webアプリケーションデプロイメント記述子のDTDで要求される要素の順序を必ず守ってください!詳細については、サーブレット仕様を参照してください。
3. アプリケーションでこのリソースを使用するコードを記述する
このリソース環境参照の典型的な使用例は次のようになります。
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory");
writer.println("foo = " + bean.getFoo() + ", bar = " +
bean.getBar());
4. Tomcatのリソースファクトリを設定する
Tomcatのリソースファクトリを設定するには、このWebアプリケーションの<Context>
要素に、次のような要素を追加します。
<Context ...>
...
<Resource name="bean/MyBeanFactory" auth="Container"
type="com.mycompany.MyBean"
factory="com.mycompany.MyBeanFactory"
singleton="false"
bar="23"/>
...
</Context>
リソース名(ここではbean/MyBeanFactory
)がWebアプリケーションデプロイメント記述子で指定された値と一致する必要があることに注意してください。また、bar
プロパティの値も初期化しており、これにより新しいBeanが返される前にsetBar(23)
が呼び出されます。foo
プロパティは初期化していませんが(初期化することもできます)、Beanにはコンストラクタによって設定されたデフォルト値が含まれます。
また、アプリケーション開発者の観点から見ると、リソース環境参照の宣言と新しいインスタンスを要求するために使用されるプログラミングは、汎用JavaBeanリソースの例で使用されるアプローチと同一であることにも注意してください。これは、JNDIリソースを使用して機能をカプセル化する利点の1つを示しています。互換性のあるAPIを維持する限り、リソースを使用するアプリケーションを必ずしも変更することなく、基になる実装を変更できます。