JNDI リソースの使い方

目次

はじめに

Tomcat は、その下で実行されている各 Web アプリケーションに対して、Jakarta EE アプリケーションサーバーが提供するものと互換性のある方法で、JNDI InitialContext 実装インスタンスを提供します。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. はじめに

このリソースファクトリは、標準の JavaBeans ネーミング規則(つまり、引数のないコンストラクタを持ち、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 を実行しているユーザーのデフォルトのファイル権限が継承されます。インストールのセキュリティを維持するために、これらの権限が適切であることを確認してください。

Realm で参照される場合、UserDatabase はデフォルトで pathname の変更を監視し、最終変更時刻に変更が observed された場合にファイルをリロードします。これは、watchSource 属性を false に設定することで無効にできます。

3. Realm の設定

Realm 設定ドキュメントに記載されているように、このリソースを使用するように UserDatabase Realm を設定します。

DataSource UserDatabase リソース

0. はじめに

Tomcat には、バックエンドとして DataSource リソースを使用する UserDatabase も含まれています。バックエンドリソースは、それを使用するユーザーデータベースと同じ JNDI コンテキストで宣言する必要があります。

グローバル UserDatabase リソースを設定するために必要な手順を以下に示します。

1. データベーススキーマ

ユーザーデータベースのデータベーススキーマは柔軟です。ユーザー(ユーザー名、パスワード)のテーブルと、各ユーザーに関連付けられたロールを一覧表示するもう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

「グループ」、「グループロール」、および「ユーザーグループ」テーブルで、グループの名前を含む列の名前。

groupRoleTable

groupNameCol 属性と roleNameCol 属性で名前が付けられた列を含む必要がある「グループロール」テーブルの名前。

groupTable

groupNameCol 属性で名前が付けられた列を含む必要がある「グループ」テーブルの名前。

readonly

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

roleAndGroupDescriptionCol

「ロール」テーブルと「グループ」テーブルで、ロールとグループの説明を含む列の名前。

roleNameCol

「ロール」、「ユーザーロール」、および「グループロール」テーブルで、対応するユーザーに割り当てられたロール名を含む列の名前。

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

roleTable

roleNameCol 属性で名前が付けられた列を含む必要がある「ロール」テーブルの名前。

userCredCol

「ユーザー」テーブルで、ユーザーの資格情報(つまりパスワード)を含む列の名前。 CredentialHandler が指定されている場合、このコンポーネントは、パスワードが指定されたアルゴリズムでエンコードされていると想定します。そうでない場合、それらはクリアテキストであると見なされます。

userGroupTable

userNameCol 属性と groupNameCol 属性で名前が付けられた列を含む必要がある「ユーザーグループ」テーブルの名前。

userNameCol

「ユーザー」、「ユーザーグループ」、および「ユーザーロール」テーブルで、ユーザーのユーザー名を含む列の名前。

userFullNameCol

「ユーザー」テーブルで、ユーザーのフルネームを含む列の名前。

userRoleTable

userNameCol 属性と roleNameCol 属性で名前が付けられた列を含む必要がある「ユーザーロール」テーブルの名前。

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

userTable

userNameCol 属性と userCredCol 属性で名前が付けられた列を含む必要がある「ユーザー」テーブルの名前。

4. Realm の設定

Realm 設定ドキュメントに記載されているように、このリソースを使用するように UserDatabase Realm を設定します。

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 プラットフォームの仕様では、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:PreparedStatement と CallableStatement をプールするかどうか。デフォルト:false
  • maxOpenPreparedStatements - ステートメントプールから同時に割り当てることができるオープンステートメントの最大数。デフォルト:-1(無制限)
  • defaultCatalog - デフォルトカタログの名前。デフォルト:設定なし
  • connectionInitSqls - 接続の作成後に一度だけ実行される 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 クラスの新しいインスタンスを無条件に作成し、このファクトリを構成する <ResourceParams> 要素に含まれるパラメータに基づいてそのプロパティを設定しています(下記参照)。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 を維持する限り、リソースを使用するアプリケーションを変更せずに、基になる実装を変更できます。