目次 | 前の項目 | 次の項目 | JNDI API |
JNDI には、
Context
およびDirContext
という 2 つのコアインタフェースがあります。DirContext
は、ディレクトリサービス操作を持った、Context
の基本ネーミング操作を拡張したものです。これらのインタフェースは、モジュール性、および JNDI の「使用するものにだけ返す」という方針に基づいて分割されました。ネーミングは、ファイルシステム、スプレッドシート、カレンダサービス、ディレクトリサービスなど、多くのコンピューティングサービスで使用される基本コンポーネントです。ネーミング操作のベースとなる
Context
インタフェースでは、ディレクトリサービス以外にこれらのサービスでもネーミングを使用できます。
Context
を拡張したDirContext
では、ディレクトリサービスの基本操作が提供されます。DirContext
で提供される操作には、名前付きオブジェクトに関連付けられた属性の操作、属性に基づく検索、および属性と名前付きオブジェクトに関するスキーマ関連の操作が含まれます。
JNDI は、4 つのクライアントパッケージ (
javax.naming
、javax.naming.directory
、javax.naming.event
、javax.naming.ldap
)、および 1 つのサービスプロバイダパッケージ (javax.naming.spi
) に分割されています。各パッケージには、特定のカテゴリのアプリケーションで必要なインタフェースおよびクラスが含まれており、ここでも、JNDI の「使用するものにだけ返す」という方針が維持されています。たとえば、名前のルックアップだけを行うアプリケーションの場合は、javax.naming
パッケージ以外は使用する必要がありません。オブジェクトに関連付けられた属性の検査および変更を行うアプリケーションの場合は、javax.naming
パッケージおよびjavax.naming.directory
パッケージを使用します。LDAP 固有のコントロールまたは拡張操作を使用する必要があるアプリケーションの場合は、javax.naming.ldap
パッケージを使用します。アプリケーション作成者は、クラスと、インタフェースについて、どれが必要で、どれを使用するかを、アプリケーションのカテゴリごとに、順に考慮していく必要があります。
JNDI では、サービスプロバイダ関連のインタフェースおよびクラスから、クライアントアプリケーションで使用されるインタフェースおよびクラスが分割され、いくつかのパッケージが作成されています。たとえば、クライアントでは
javax.naming
のインタフェースとクラスが使用され、ネームサービスに接続されたサービスプロバイダではjavax.naming
およびjavax.naming.spi
が使用される場合があります。パッケージを分割することにより、アプリケーション開発者の混乱が少なくなり、プログラムを作成するときに検討するパッケージを明確に区別できます。
コンテキストの一覧を出力するアプリケーションには、2 種類のアプリケーションがあります。1 つはブラウザ型のアプリケーションで、もう 1 つはコンテキスト内のすべてのオブジェクトに対して操作を実行するアプリケーションです。ブラウザ型のアプリケーションの場合は通常、コンテキストの内容の名前が表示されます。多くのブラウザでは、名前以外に、名前にバインドされたオブジェクトの型情報が必要です。 型情報に応じて、オブジェクトの画像表現が適切に表示されます。このブラウザは通常、対話型です。ブラウザを使用してコンテキストの内容が表示されたときに、表示されたエントリからいくつかのエントリを選択すると、そのエントリの詳細情報が表示されます。
一部のアプリケーションでは、コンテキスト内のすべてのオブジェクトに対して操作を実行する必要があります。たとえば、バックアッププログラムでは、ファイルディレクトリ内のすべてのオブジェクトに対して、「file stats」操作を実行します。また、プリンタ管理プログラムでは、1 つの建物内にあるすべてのプリンタを再起動します。これらの操作を実行するには、プログラムでは、コンテキストにバインドされているすべてのオブジェクトを取得する必要があります。
これらの 2 種類の使用法を前提として、
Context
インタフェースには、list()
およびlistBindings()
という 2 種類のリストメソッドがあります。list()
は、名前とクラス名を対で返します。listBindings()
は、名前、クラス名、およびオブジェクトを 3 つ合わせて返します。list()
は、コンテキストにバインドされたオブジェクトの名前および型だけを主に必要とする、ブラウザ型のアプリケーション用に設計されています。listBindings()
は、名前および型以外に、コンテキスト内のすべてのオブジェクトを取得する必要があるアプリケーション用に設計されています。listBindings()
は、Binding
の列挙を返します。listBindings()
操作とBinding
クラスのメソッド (getObject()
など) の呼び出しは、適宜最適化されます。listBindings()
を使用する場合は、呼び出し側がコンテキスト内のすべてまたはほとんどのオブジェクトを取得することを前提として、実装がコンテキストに対して最適化されます。list()
を使用する場合は、呼び出し元が必ずしもコンテキスト内のすべてのオブジェクトを取得しないことを前提として、実装がコンテキストに対して最適化されます。代わりに、1 つのリスト操作だけを実装した場合は、
Binding
の実装の一部として動作が最適化されます。この方法の利点は、理解が必要なリスト操作が 1 つだけになることです。ただし、リストから返される情報を呼び出し側から指定できなくなり、プログラムの目的の動作に応じて実装が最適化されなくなります。
連合は、JNDI の重要な概念です。クライアントインタフェースでは、1 つ以上の名前空間にまたがる名前を指定するときに、
Name
インタフェースを使用できます。クライアントインタフェースのメソッドの呼び出し側では、連合の情報は必要ありません。複数のシステムにまたがる名前は SPI によって解決されるため、呼び出し側の介入は発生しません。連合は重要な概念ですが、すべての呼び出し側およびサービスプロバイダで連合を使用する必要はありません。アプリケーションまたはサービスで連合を使用しない場合は、
Name
は複数の名前空間にまたがる必要はありません。Name
では、1 つの名前空間内でオブジェクトの名前付けが行われます。 SPI では、複数の名前空間のサポートの一部として、1 つの名前空間内で名前が解決されます。
DirContext
がContext
を拡張する代わりに、Context
を拡張しないで、DirObject
と呼ばれる別のインタフェースを使用することもできます。DirObject
では、ディレクトリ関連のメソッドがすべてカプセル化されます。この場合、オブジェクトでネーミングおよびディレクトリ操作がサポートされているときは、Context
およびDirObject
を実装できます。 ネーミングおよびディレクトリ操作がサポートされていないときは、DirObject
だけを実装できます。
DirContext
を削除するときは、ネーミングとディレクトリの両方の操作を含むハイブリッド操作が組み込まれていることが問題になります。 具体的には、属性を引数として指定できるbind()
およびcreateSubcontext()
メソッドが組み込まれています。これらの操作を保持しながらDirObject
を使用するには、第 3 のインタフェース (多くの場合、DirContext
) にもこれらのハイブリッド操作が組み込まれていなければなりません。
DirObject
の代わりにDirContext
を使用すると、1 つの手続きでいくつかの操作を実行でき、2 つの手続きを実行する必要はありません。たとえば、DirContext.getAttributes()
を使用すれば、名前付きオブジェクトに関連付けられた属性を取得できます。 ただし、DirObject
を使用するときは、まずオブジェクト (Context.lookup()
) を解決してから、DirObject.getAttributes()
を使用してその属性を取得する必要があります。
DirContext
インタフェースでは、スキーマがサポートされています。たとえば、DirContext
オブジェクトからスキーマオブジェクトを取得できます。 スキーマオブジェクトは、この特定のDirContext
インスタンスのスキーマが定義されているディレクトリ空間を指しています。DirContext
オブジェクトから、スキーマのクラス定義を取得することもできます。 クラス定義とは、ディレクトリ内で表現されるオブジェクトの型に関する情報のことです。Attribute
クラスでもスキーマがサポートされています。Attribute
クラスには、属性の構文情報 (属性値の型) および属性の定義 (複数値かどうか、構文、構文に対する制約など) を取得するためのメソッドが含まれています。このスキーマ情報に動的にアクセスできる (ライブディレクトリ空間を指している) 必要はありません。このスキーマ情報のサポートは、サービスプロバイダによって静的に生成される場合もあります。たとえば、特定のディレクトリサービスでは、文字列の属性値以外はサポートされていないことがあります。 この場合は、属性を返すときに属性の構文が強制的に適用されます。ディレクトリによっては、静的スキーマ (スキーマ内の情報を変更できない) 以外はサポートされていないことがあります。また、動的スキーマがすべてサポートされているディレクトリもあります。DirContext
内のインタフェースとクラスは、柔軟性が高く、これらのさまざまなスキーマがサポートされています。
Context
およびDirContext
インタフェース内のName
引数を指定するすべてのメソッドには、名前を指定するときにString
引数を指定するオーバーロードが必ず存在します。
String
ベースのメソッドは、エンドユーザから文字列の名前を受け取り、その名前のオブジェクトに対してコンテキストメソッドを実行するアプリケーションが多い場合に使用します。これらのアプリケーションでは、コンテキストメソッドでその名前の文字列を直接受け取るときに、この形式のメソッドを使用します。 この場合、文字列の名前を使用して、最初にName
オブジェクトを構築する必要はありません。
Name
ベースのメソッドは、名前を操作するアプリケーションが多く、名前の作成および変更を行うときに名前の文字列の構文への対応を省略したい場合に使用します。これらのアプリケーションでは、構文解析された名前が処理されるので、文字列の名前よりName
オブジェクトが処理に適しています。このため、コンテキストインタフェースでは、Name
ベースのメソッドが使用されます。これらのメソッドを使用しない場合は、JNDI の上位で開発されたアプリケーションで使用されている形式の名前を操作するために、Name
形式のインタフェースやクラスが必要以上に生成されることになります。
アプリケーションおよびサービスからディレクトリを使用してオブジェクトを検索する場合、さまざまな方法があります。JNDI は汎用性が高いので、さまざまなモデルに対応することができます。たとえば、ディレクトリ内のオブジェクトが、オブジェクト自体にバインドされることがあります。アプリケーションがアクティブなときに動的ディレクトリが構築され、アプリケーションが終了するとそのディレクトリが削除されることもあります。名前空間内でオブジェクトを検索するための属性として、URL を格納することもあります。システムによっては、ディレクトリ内の一部の参照情報がバインドされ、実際のオブジェクトの検索またはアクセスを行うときにその情報が使用されることもあります。インストール済みのベースに実装されているサービスを Java アプリケーションで使用するときに、この最後の例がよく使用されます。このディレクトリ内の参照は、実際のオブジェクトへのポインタとして機能します。
JNDI には
Reference
クラスが定義されており、参照情報を表現するための方法が統一されています。Reference
には、オブジェクトへのアクセス方法に関する情報が含まれています。この情報は、アドレスのリスト、およびこの参照が表現するオブジェクトのクラス情報で構成されます。つまり、ディレクトリ内で参照として表現されるオブジェクトに名前をバインドしたときは、オブジェクトの参照の展開およびバインドが行われることになります。この動作を実現するには、そのオブジェクトのクラスで、getReference()
メソッドが組み込まれたReferenceable
インタフェースを実装する必要があります。
Serializable
インタフェースとReferenceable
インタフェースは類似していますが、Serializable
は使用しません。直列化されたオブジェクトの場合は、そのオブジェクトは固定されていますが、参照の場合は、オブジェクトの構築に必要な情報だけが含まれています。また、直列化されたオブジェクトには、ディレクトリへの格納に適していない状態が多く含まれている可能性があります。
ディレクトリ内で
Reference
としてバインドされているオブジェクトでは、JNDI SPI フレームワークによって、参照によって特定されたオブジェクトの生成およびインスタンスの生成が自動的に行われます。このとき、プログラムでは、lookup()
の結果が目的のクラスにナロー変換されます。lookup()
の結果を目的のクラスのオブジェクトに変換する操作は呼び出されません。たとえば、プリンタオブジェクトをルックアップしている場合は、ルックアップが正常終了したときにプリンタオブジェクトが返され、それを直接使用することができます。
Printer prt = (Printer) ctx.lookup(somePrinterName); prt.print(someFileName);JNDI では、この処理が自動的に実行されます。 明示的な変換ステップは必要ありません。 この処理が標準で使用されることを前提としています。JNDI では、
Reference
クラス、およびReference
クラスをこのクラスによって特定されたオブジェクトに変換する共通の機構を提供しています。 このため、各アプリケーションおよびシステムプロバイダに対して、独自の機構を開発せずにこの機構を利用することを推奨しています。