Post

Spring Boot を WAR で Tomcat に載せると、なぜ `context.xml` まで必要になるのか

Spring Boot を WAR で Tomcat に載せると、なぜ `context.xml` まで必要になるのか

Spring Boot を WAR で Tomcat に載せると、なぜ context.xml まで必要になるのか

Spring Boot を外部 Tomcat に WAR としてデプロイすると、JNDI の DataSource 設定は少し分かりにくくなります。
application-server.ymlspring.datasource.jndi-name を書いたのに起動しない、という状況は珍しくありません。

今回のポイントは単純です。

  • Spring Boot は「アプリがどの JNDI 名を使うか」を知る必要がある
  • Tomcat は「その JNDI Resource をこの Web アプリに見せるか」を知る必要がある

つまり、application.yml 系の設定と context.xml の設定は役割が違います。

1. dev はローカル直結、server は JNDI

ローカル開発では JDBC URL を直接使い、サーバでは JNDI を使う構成が扱いやすいです。

src/main/resources/application-dev.yml

1
2
3
4
5
6
7
8
9
server:
  address: 127.0.0.1
  port: 8817

spring:
  config:
    import: optional:file:${user.home}/.config/tsnoticeapproval/dev-secrets.yml
  datasource:
    driver-class-name: com.sybase.jdbc4.jdbc.SybDriver

src/main/resources/application-server.yml

1
2
3
spring:
  datasource:
    jndi-name: java:comp/env/jdbc/my-db

src/main/resources/application.yml

1
2
3
4
5
spring:
  application:
    name: TsNoticeApproval
  profiles:
    default: server

この時点で Spring Boot は、サーバ環境では java:comp/env/jdbc/my-db を探しに行きます。
ただし、ここで Tomcat 側にその名前が見えていなければ失敗します。

2. application-server.yml だけでは足りない理由

spring.datasource.jndi-name は、Spring に対して

「この名前で DataSource を lookup してください」

と伝えているだけです。

一方で、Tomcat 側には

「その jdbc/my-db をこの Web アプリの java:comp/env にぶら下げる」

という設定が必要な場合があります。

そこで使うのが context.xml です。

src/main/webapp/META-INF/context.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <ResourceLink
        name="jdbc/my-db"
        global="jdbc/my-db"
        type="javax.sql.DataSource"/>
</Context>

この設定は、

  • Tomcat 全体で定義されている jdbc/my-db
  • それをこのアプリから java:comp/env/jdbc/my-db として参照できるようにする

という意味です。

3. よくある誤解

「JNDI 名は合っているのに、なぜ見つからないのか?」

これは名前の打ち間違いではなく、Tomcat の naming context に bind されていないことが原因です。
ログに Name [jdbc/my-db] is not bound in this Context と出るなら、その可能性が高いです。

要するに:

  • application-server.yml は Spring Boot 向け
  • context.xml は Tomcat 向け

同じことを二重に書いているように見えて、実際には別レイヤの設定です。

4. では、普通の JDBC 設定の方が楽では?

はい。運用フローによってはその通りです。

もし管理者が Tomcat の JNDI を管理していて、複数アプリで共通 DataSource を使うなら JNDI は自然です。
逆に、WAR を置くだけの運用なら、application-server.yml に JDBC URL を直接書く方が単純です。

短く言うと:

  • JNDI は「コンテナ管理」に向いている
  • 直接 JDBC は「デプロイ簡素化」に向いている

5. まとめ

Spring Boot が面倒というより、WAR + 外部 Tomcat + JNDI の組み合わせが面倒です。
application-server.yml は Spring の設定、context.xml は Tomcat の接続設定です。

そのため、Spring Boot を WAR で配布し、Tomcat 上の JNDI DataSource を使う場合は、application-server.yml だけでなく context.xml まで必要になることがあります。

This post is licensed under CC BY 4.0 by the author.