Java Naming and Directory Interfaceの概要

1. 前書き

Java Naming and Directory Interface(JNDI)* Java APIとしてのネーミングおよび/またはディレクトリサービスの一貫した使用を提供します。*このインターフェースは、オブジェクトのバインド、オブジェクトの検索またはクエリ、および同じオブジェクトの変更の検出に使用できます。
JNDIの使用にはhttps://docs.oracle.com/javase/8/docs/technotes/guides/jndi/index.html [サポートされているネーミングサービスとディレクトリサービス]のさまざまなリストが含まれていますが、このチュートリアルではJDBCに焦点を当てます。 JNDIのAPIを調査中。

2. JNDIの説明

JNDIでの作業には、*基盤となるサービスの理解*と*アクセス可能な実装*が必要です。たとえば、データベース接続サービスは特定のプロパティと例外処理を必要とします。
ただし、JNDIの抽象化により、接続構成がアプリケーションから分離されます。
JNDIのコア機能を含む_Name_と_Context_を調べてみましょう。

2.1. _Name_インターフェイス

Name objectName = new CompositeName("java:comp/env/jdbc");
_Name_インターフェースは、コンポーネント名とJNDI名の構文を管理する機能を提供します。 文字列の最初のトークンはグローバルコンテキストを表し、追加された各文字列は次のサブコンテキストを表します。
Enumeration<String> elements = objectName.getAll();
while(elements.hasMoreElements()) {
  System.out.println(elements.nextElement());
}
出力は次のようになります。
java:comp
env
jdbc
ご覧のとおり、_ / _は_Name_サブコンテキストの区切り文字です。 次に、サブコンテキストを追加しましょう。
objectName.add("example");
次に、追加をテストします。
assertEquals("example", objectName.get(objectName.size() - 1));

2.2. _Context_インターフェイス

_Context_には、ネーミングとディレクトリのプロパティが含まれています。
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.activate();
Springの_SimpleNamingContextBuilder_はJNDIプロバイダーを作成し、https://docs.oracle.com/javase/8/docs/api/javax/naming/spi/NamingManager.html [_NamingManager_]でビルダーをアクティブにします。
JndiTemplate jndiTemplate = new JndiTemplate();
ctx = (InitialContext) jndiTemplate.getContext();
最後に、__ JndiTemplate __は_InitialContext_へのアクセスを支援します。

3. JNDIオブジェクトのバインドとルックアップ

_Name_と_Context_の使用方法を確認したので、JNDIを使用してJDBC _DataSource_を保存しましょう。
ds = new DriverManagerDataSource("jdbc:h2:mem:mydb");

3.1. JNDIオブジェクトのバインド

コンテキストがあるので、オブジェクトをそれにバインドしましょう:
ctx.bind("java:comp/env/jdbc/datasource", ds);
一般に、サービスはオブジェクト参照、シリアル化されたデータ、または属性をディレクトリコンテキストに格納する必要があります。 それはすべて、アプリケーションのニーズに依存します。
この方法でJNDIを使用することはあまり一般的ではないことに注意してください。 通常、JNDIは、アプリケーションランタイムの外部で管理されるデータとインターフェイスします。
ただし、アプリケーションがすでにその_DataSource_を作成または検索できる場合は、Springを使用して簡単に配線できます。 対照的に、アプリケーションの外側にあるものがJNDIのオブジェクトにバインドされている場合、アプリケーションはそれらを消費する可能性があります。

3.2. JNDIオブジェクトの検索

_DataSource_を検索してみましょう。
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
そして、_DataSource_が期待どおりであることをテストしてみましょう:
assertNotNull(ds.getConnection());

4. 一般的なJNDI例外

JNDIを使用すると、実行時例外が発生する場合があります。 一般的なものを次に示します。

4.1. _ NameNotFoundException _

ctx.lookup("badJndiName");
この名前はこのコンテキストにバインドされていないため、次のスタックトレースが表示されます。
javax.naming.NameNotFoundException: Name [badJndiName] not bound; 0 bindings: []
  at org.springframework.mock.jndi.SimpleNamingContext.lookup(SimpleNamingContext.java:140)
  at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
スタックトレースにはバインドされたすべてのオブジェクトが含まれていることに注意してください。これは、例外が発生した理由を追跡するのに役立ちます。

4.2. _ NoInitialContextException _

_InitialContext_とのやり取りでは、_NoInitialContextException_がスローされます。
assertThrows(NoInitialContextException.class, () -> {
  JndiTemplate jndiTemplate = new JndiTemplate();
  InitialContext ctx = (InitialContext) jndiTemplate.getContext();
  ctx.lookup("java:comp/env/jdbc/datasource");
}).printStackTrace();
以前に使用したように、このJNDIの使用は有効であることに注意してください。 ただし、今回はJNDIコンテキストプロバイダーが存在せず、例外がスローされます。
javax.naming.NoInitialContextException: Need to specify class name in environment or system property,
  or in an application resource file: java.naming.factory.initial
    at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:685)

5. 最新のアプリケーションアーキテクチャにおけるJNDIの役割

  • JNDIは、Spring Bootなどの軽量のコンテナ化されたJavaアプリケーション*ではあまり役割を果たしませんが、他の用途もあります。 まだJNDIを使用している3つのJavaテクノロジーは、https://www.baeldung.com/java-jdbc [JDBC]、https://www.baeldung.com/ejb-intro [EJB]、およびhttps://www.baeldungです。 .com / spring-jms [JMS]。 Javaエンタープライズアプリケーション全体で幅広い用途があります。

    たとえば、別のDevOpsチームが、すべての環境の機密データベース接続のユーザー名やパスワードなどの環境変数を管理する場合があります。 JNDIリソースは、すべての環境で機能する一貫した抽象化のレイヤーとして使用されるJNDIを使用して、Webアプリケーションコンテナーで作成できます。
    このセットアップにより、開発者は、開発目的でローカル定義を作成および制御しながら、同じJNDI名を介して本番環境の機密リソースに接続できます。

6. 結論

*このチュートリアルでは、Java Naming and Directory Interfaceを使用してオブジェクトを接続、バインド、検索しました。* JNDIによってスローされる一般的な例外も確認しました。
最後に、JNDIが最新のアプリケーションアーキテクチャにどのように適合するかを見ました。
いつものように、コードはhttps://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-jndi[GitHubで利用可能]です。