JNDIをさらっと振り返る
JBoss Advent Calendar 2011の12日目のエントリです。
JNDIはJava EEサーバのEJB、JDBCデータソースやJMSのConnectionFactoryなど、各種サービスにアクセスするためのエントリポイントとなる部分なのですが、あまりエキサイティングな技術ではないので注目されることはないですし、どのようなものなのかを調べたりする機会もなかなかないでしょう。というわけでさらっと振り返ります。
まず基本的な機能はリモートアクセスもできるサーバ上のグローバルHashMapみたいなものです。メソッド名がちょっと違い、get()ではなくlookup()、put()ではなくrebind()となっています。
データソースを取得するようなコードはこのようになります。
InitialContext context = new InitialContext(); DataSource ds = (DataSource)context.lookup("java:DefaultDS");
lookup()の引数ですが、以下で始まるものは少し特殊な意味を持ちます。
上記以外はグローバル空間ということになります。現在はjava:compを使うようなコンポーネントローカル空間を使って各コンポーネントを隔離する、という厳格な設計はあまり流行っておらず、必要性が無ければ単にグローバル空間を自由に使う、というスタイルのほうが主流だと思います。
JNDIにリモートアクセスするにはjndi.peopertiesをクラスパス上に配置するか、InitialContextをnewするときに接続先情報を渡します。古いAPIのためパラメータの型がHashtableだったりしますが、Propertiesクラスを利用するほうがふさわしいと思うので個人的にはHashtableではなくPropertiesを利用しています。
Properties props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); props.put(Context.PROVIDER_URL, "localhost:1099"); InitialContext context = new InitialContext(props);
jndi.peopertiesの場合は以下のように記述します。jndi.peopertiesをクラスパスに含める場合はInitialContextをnewするときにパラメータ指定は必要ありません。Java EEコンテナ上では元々コンテナ側でjndi.peopertiesが設定されているはずなので、Java EEコンテナ上にデプロイするアプリケーションなどにjndi.propertiesを含めてはいけません。JNDIアクセスが誤動作します。
jndi.peopertiesは上記のようないろいろな制約を生みやすいので、単純なケース以外では基本的には使わないほうが無難です。
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.factory.url.pkgs=jboss.naming:org.jnp.interfaces java.naming.provider.url=localhost:1099
他にJNDIはRMIレジストリとして機能したり、LDAPへのアクセスインタフェースとなったりもしますが、あまり使うことはないので省略します。