JNDIリソース設定方法

目次

はじめに

Tomcatは、WebアプリケーションごとにJNDIのInitialContext実装インスタンスを提供します。これは、Jakarta EEアプリケーションサーバーが提供するものと互換性のある方法で行われます。Jakarta EE標準は、リソースを参照/定義するために、/WEB-INF/web.xmlファイルに標準の要素セットを提供します。

JNDIのプログラミングAPI、およびTomcatが提供するサービスについてエミュレートするJakarta EEサーバーがサポートする機能の詳細については、以下の仕様を参照してください。

web.xml設定

Webアプリケーションにリソースを定義するには、Webアプリケーションデプロイメント記述子(/WEB-INF/web.xml)で以下の要素を使用できます。

  • <env-entry> - 環境エントリ。アプリケーションの動作を設定するために使用できる単一値パラメータです。
  • <resource-ref> - リソース参照。通常、JDBC DataSource、Jakarta Mail Session、または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

groupNameColおよびroleNameCol属性で指定されたカラム名を含む必要がある「グループロール」テーブルの名前。

groupTable

groupNameCol属性で指定されたカラム名を含む必要がある「グループ」テーブルの名前。

readonly

これがtrueに設定されている場合、saveメソッドを使用してUserDatabaseへの変更をDataSourceに永続化できます。デフォルト値はtrueです。

roleAndGroupDescriptionCol

"roles"および"groups"テーブル内の、ロールとグループの説明を含むカラムの名前。

roleNameCol

"roles"、"user roles"、"group roles"テーブル内の、対応するユーザーに割り当てられたロール名を含むカラムの名前。

この属性は、ほとんどの設定で必須です。省略可能な稀なケースについては、関連するレルムのallRolesMode属性を参照してください。

roleTable

roleNameCol属性で指定されたカラム名を含む必要がある「ロール」テーブルの名前。

userCredCol

"users"テーブル内の、ユーザーの資格情報(つまりパスワード)を含むカラムの名前。CredentialHandlerが指定されている場合、このコンポーネントはパスワードが指定されたアルゴリズムでエンコードされていると仮定します。それ以外の場合は、クリアテキストであると仮定されます。

userGroupTable

userNameColおよびgroupNameCol属性で指定されたカラム名を含む必要がある「ユーザーグループ」テーブルの名前。

userNameCol

"users"、"user groups"、"user roles"テーブル内の、ユーザー名を含むカラムの名前。

userFullNameCol

"users"テーブル内の、ユーザーのフルネームを含むカラムの名前。

userRoleTable

userNameColおよびroleNameCol属性で指定されたカラム名を含む必要がある「ユーザーロール」テーブルの名前。

この属性は、ほとんどの設定で必須です。省略可能な稀なケースについては、関連するレルムのallRolesMode属性を参照してください。

userTable

userNameColおよびuserCredCol属性で指定されたカラム名を含む必要がある「ユーザー」テーブルの名前。

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をダウンロードする.

ディストリビューションを展開し、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に関する情報については、以下を参照してください。

- 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 - デフォルトのトランザクション分離レベルを設定します。NONEREAD_COMMITTEDREAD_UNCOMMITTEDREPEATABLE_READSERIALIZABLEのいずれかを指定できます。デフォルト:設定なし
  • 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を維持する限り、リソースを使用するアプリケーションを必ずしも変更することなく、基になる実装を変更できます。