しいしせねっとわーく Amazon.co.jpアソシエイト
[技術資料室] [Java] [J2EE]

Java Naming and Directory Interface(JNDI) ってなんぞ?

おしながき

はじめに

J2EEの環境(Tomcat等々)でJDBCのDataSourceを使うには、JNDIを使わないといけません。
その他、最近いろんなものを使うのにはJNDIを参照するという場面が目立ちます。で、JNDIへ漂流してきてしまいます。J2EEではJNDIはフレームワークが管理してくれます。そのまま気にしないで使えればいいのですが、気になってしまいますので、JNDIについて調べてみることにしましょう。

参考

JNDI2つの役割

ネームサービスやディレクトリサービスをまとめたようなもの、といわれていますが、役割としては、2つあります。

  1. DNS、LDAPなどの階層構造のデータ引きに対応する共通API
  2. JDBC、EJBなどのオブジェクトを階層構造を持って命名し、インスタンスをアプリケーションに提供するために登録する環境変数のようなもの

URL的な名前から、いろいろ探せるのかな? 環境変数をドメイン(DNS)やディレクトリのように階層化したものです。その中に、Javaのクラスをパッケージで分けるのと似たような感じです。
ドライバを用意することで、LDAP、DNSなどのディレクトリ型(階層型)項目を持つデータにも同じAPIでアクセスすることができます。

EJBの抽象的な名前を付けるのにも使っていますね。Collection機能をツリー状にしたような感じでもあり。
J2SEに搭載されていますが、主にJ2EEで活躍しています。JNDIには、いろいろな機能をSPIとして組み込んで使えるような仕組みが用意されているので、まずはそれらから見ていくのがよいのではないでしょうかと。

J2EEでは、Tomcatのようなコンテナと、その上で実行されるサーブレットやEJBのようなアプリケーションがあります。JNDIでは、アプリケーションで利用するためにコンテナ側に登録するためのものです。このように分けることで、1つのWebアプリケーションをJNDIの環境を変えるだけで違った動作をさせたり別のデータベースやEJBなどにアクセスさせたりすることができるようになります。

この2つは、どちらも他のところで設定された値を読んだりするということで共通ですので、JNDIとしてまとめられています。相互に何か関係あるというわけではないようです。J2EEで利用されているのは主に環境変数としてEJBなどを登録します。環境変数も、JNDIのドライバを書けば、複数マシンで共有することもできるかもしれません。オブジェクトを参照しながら他のオブジェクトを探して使うよりは、カスタマイズも楽になり、各機能の独立性が高まります。

利用までの簡単な流れ

  1. J2EEのコンテナなどのフレームワークがconfigファイルなどからJNDIリソース情報を読込み、JNDIに必要なリソースを登録する
  2. アプリケーションがそれをJNDIのDataSourceなどから参照名を使って呼び出し、利用する

という流れになります。簡単に言ってしまえばアプリケーション内で使える環境変数やレジストリのようなものです。登録されているのは名前ではなくJavaのオブジェクトです。

SPIを利用して、新規のネームサービス、ディレクトリサービスを拡張することも可能です。

JNDI自体はネットワーク上のプロトコルではないようです。J2EEでは分散して使えるようなので、ネットワークからも使えるのかもしれませんが。RMIやJiniなどでは使えない?

JNDI (のAPI)を使用しているもの/利用できるもの

名前空間

各各いろいろは、名前空間を持っているので、それらをまず別々に見てみるのがよいのかもしれません。トップの名前空間で基本的にプロトコル等の選択になるようです。

この命名で使うのは、参照名(Webアプリ内のコードで固定的に使う名前)です。JNDI名(連携するための共通名)は、これとは別でもいいのかもしれませんが、TomcatなどではJNDI名を参照名と同じにしておくと、web.xmlで参照名とJNDI名を関連づけていなくてもそのまま使えます。(Tomcat 5ではweb.xml が必要・・・か?)

設定ファイル等々には、ejb/~ や jdbc/~ のところから記述します。ソースファイル中では、java:comp/env から書きます。

システム構成

サーバとか、そういうものは無いようです。各SPIが参照できるサービスが別途必要かもしれません。
LDAPを参照するのならOpenLDAP等のLDAPのサーバ、DNSを検索するのならBIND等のDNSサーバ、RMIの場合は?、等々。

J2EEで使うには?

J2EEでは、JNDIを通して各オブジェクトが結びつけられており、JNDIはレジストリのように環境変数を保存する役割を持っています。

登録方法は、各J2EEアプリケーションサーバやTomcatなど、それぞれ異なります。設定ファイルなども別々ですので各アプリケーションサーバの手順に従ってJNDIリソースを登録します。

[J2EEのJDNI]

DNSサービスプロバイダを使ってみる

DNSを例にして、まずはJNDIの初期的なところがどうなっているのか眺めてみましょう。
DNSの場合利用するのはjavax.naming.directory パッケージです。
http: ftp: と同様のプロトコルの疑似表記として dns: を使います。JDBCもjdbc: というのをjava.sql.DriverManagerで使ってますね。
dns:[//host[:port]][/domain]

dns://ns.example.com/siisise.net
dns:/siisise.net

DNSサーバを省略してもよし。

// 初期化は適度に簡単にできてしまうらしいです。
DirContext ctx = new InitialDirContext();
// 調べたい項目を指定して、チェック。attrs に一致する一覧が登場します。どっちでもいいらしい
Attributes attrs = ctx.getAttributes("dns://ns.example.org/siisise.net", new String[] {"MX"});
Attributes attrs = ctx.getAttributes("dns://ns.example.org/siisise.net");
// MXレコードを抽出
Attribute attr = attrs.get("MX");
// MXの各要素抽出
attr.size(); // 複数あったりなかったり
attr.get(0);

MXレコードの場合は "10 mail.example.com."のような文字列として取得できます。

参考

Get Thunderbird


[しいしせねっと] [Java.dev.jp]