Spring Boot を WAR で Tomcat に載せると、なぜ `context.xml` まで必要になるのか
Spring Boot を WAR で Tomcat に載せると、なぜ context.xml まで必要になるのか
Spring Boot を外部 Tomcat に WAR としてデプロイすると、JNDI の DataSource 設定は少し分かりにくくなります。
application-server.yml に spring.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 まで必要になることがあります。