Manual / JNDI・JDBC・JTA2026.10.14 · ユーザーマニュアル
CHAPTER 06 / KOHAKU

JNDI・JDBC・JTA

データソースを定義し、JNDIから取得します。共有とwebapp専用の違い、トランザクションの保証範囲を確認します。

JNDIの名前

webappの実行コンテキストから new InitialContext().lookup(...) を使います。@Resource 等の自動注入に全面的に依存する構成は現行の対応範囲ではありません。

コンテナが束縛する既定名
名前型・用途
java:comp/env/<name>env-entry、DataSource等のアプリ環境項目
java:comp/UserTransactionjavax.transaction.UserTransaction
java:comp/TransactionSynchronizationRegistryjavax.transaction.TransactionSynchronizationRegistry
java:comp/DefaultContextServicejavax.enterprise.concurrent.ContextService
java:comp/DefaultManagedExecutorServicejavax.enterprise.concurrent.ManagedExecutorService
java:comp/DefaultManagedScheduledExecutorServicejavax.enterprise.concurrent.ManagedScheduledExecutorService
java:comp/DefaultManagedThreadFactoryjavax.enterprise.concurrent.ManagedThreadFactory

サーバ共有のDataSource

conf/resources.yaml に定義します。同じ名前を参照するwebappは同じプールと接続上限を共有します。ドライバはサーバ側で読み込むため lib/ に置きます。下は接続先を置換して使う非XA例です。

conf/resources.yaml
dataSource:
  "jdbc/app":
    url: "jdbc:postgresql://db.example.invalid:5432/app"
    driverClass: org.postgresql.Driver
    user: app
    password: "CHANGE-ME"
    maxConnections: 8
    maxIdle: 8
    borrowTimeoutMillis: 30000
    validationQuery: "SELECT 1"
    queryLog: "off"
    connectionProperty:
      ApplicationName: kohaku-app
WEB-INF/web.xmlのweb-app直下
<resource-ref>
  <res-ref-name>jdbc/app</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
  <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

DataSource型のresource-refに対応する定義がない場合、参照するwebappの配備が失敗します。定義の不正値やドライバ読込失敗もそのwebappの配備失敗です。未参照の不正定義だけでサーバ全体を止めることはありません。ただしresources.yamlそのものの読込・構文エラーは起動失敗です。

dataSource.&lt;name&gt;配下の項目
項目既定・条件
url / driverClass非XAで必須。driverClassを明示しDriver#connectを呼ぶ
user / password未指定。userを省略するとpasswordも渡さない
maxConnections8。正数。停滞・物理close失敗の接続も上限に数える
maxIdle8。非負かつmaxConnections以下。接続上限だけを8未満にするならこちらも指定
borrowTimeoutMillis30000。非負・ミリ秒。空き待ちと検証・確立で同じ全体予算。検証・確立には最低1秒
validationQuery未設定。無ければConnection.isValidで生存確認
queryLogoff / safe / hash / unsafe-full
connectionProperty.<name>非XA用。user/password・空の値は不可。単位と意味はドライバ固有
xa.dataSourceClassXADataSourceの実装。XAではurl/driverClassを使わない
xa.property.<name>XADataSourceのJavaBeansプロパティ。XA定義でconnectionPropertyは不可

webapp専用のDataSource

WAR内の WEB-INF/kohaku-web.xml へ定義し、ドライバjarは WEB-INF/lib/ に置きます。同名の共有定義があればローカル定義が優先され、接続先と資格情報もローカル側になります。resource-refが無くても束縛します。この形式は非XA用です。

WEB-INF/kohaku-web.xml
<kohaku-web xmlns="urn:kohaku:web" version="1.0">
  <data-source name="jdbc/app">
    <url>jdbc:postgresql://db.example.invalid:5432/app</url>
    <driver-class>org.postgresql.Driver</driver-class>
    <user>app</user>
    <password>CHANGE-ME</password>
    <max-connections>8</max-connections>
    <max-idle>8</max-idle>
    <borrow-timeout-millis>30000</borrow-timeout-millis>
    <validation-query>SELECT 1</validation-query>
    <connection-properties>
      <ApplicationName>kohaku-app</ApplicationName>
    </connection-properties>
  </data-source>
</kohaku-web>

password要素は前後の空白も保持します。他の値は原則trimします。接続プロパティは <名前>値</名前> とし、XML要素名にできない名前はJDBC URL側で扱います。標準 web.xml の <data-source> とこのKohaku固有形式は別物です。

接続を借りて返す

Servlet等の処理内 — Javaコード断片
javax.sql.DataSource ds = (javax.sql.DataSource)
    new javax.naming.InitialContext().lookup("java:comp/env/jdbc/app");
try (java.sql.Connection connection = ds.getConnection();
     java.sql.PreparedStatement statement = connection.prepareStatement("SELECT 1");
     java.sql.ResultSet result = statement.executeQuery()) {
    if (result.next()) {
        int value = result.getInt(1);
        // value を処理する
    }
}

Connection・Statement・ResultSetを必ず閉じます。物理接続上限を超える溢れ枠はありません。ドライバ内で止まった接続も枠を保持します。全枠が停滞している場合は待たずに借用を拒否します。borrowTimeoutMillisはgetConnection全体が必ずその時間内に返る保証ではありません。同じトランザクションの二番手の予約待ち、無効接続の破棄、beginRequestやautoCommitの正規化は、ドライバ内で止まってもこの期限で打ち切りません。ドライバ自身の接続・通信期限も設定してください。

UserTransaction

リクエスト内でJNDIから取得し、begin後に借りたプール接続を使い、同じ処理内でcommit/rollbackを完了します。実行中のトランザクションを別スレッドへ任意に持ち出さないでください。

Javaコード断片 — lookupとトランザクション開始
javax.transaction.UserTransaction tx = (javax.transaction.UserTransaction)
    new javax.naming.InitialContext().lookup("java:comp/UserTransaction");
tx.setTransactionTimeout(30); // 秒。次のbeginに適用
tx.begin();
// この後でDataSourceから接続を取得し、SQLを実行する。
// 成功時はtx.commit()、失敗時は状態を確認してtx.rollback()。
// どちらの場合もJDBC資源を閉じる。

クエリログ

共有定義の queryLog は off が既定です。safe はリテラルを伏せ、hash はハッシュで識別し、unsafe-full はSQL全文を出すモードです。機密値を含むSQLにはunsafe-fullを使わないでください。webapp専用XMLにqueryLog要素はありません。

出力量の設定も conf/resources.yaml に置きます。queryLog.serverRatePerSecond は既定1000、許可範囲1〜10000回/秒。queryLog.poolRatePerSecond は既定200、1以上かつserverRatePerSecond以下です。違反はサーバ起動失敗になります。