Penamaan Java dan Ringkasan Antarmuka Direktori

1. Perkenalan

Java Naming and Directory Interface (JNDI) menyediakan penggunaan penamaan dan / atau layanan direktori yang konsisten sebagai Java API. Antarmuka ini dapat digunakan untuk mengikat objek, mencari atau membuat kueri objek, serta mendeteksi perubahan pada objek yang sama.

Meskipun penggunaan JNDI mencakup beragam daftar layanan penamaan dan direktori yang didukung, dalam tutorial ini kita akan fokus pada JDBC sambil menjelajahi API JNDI.

2. Deskripsi JNDI

Setiap pekerjaan dengan JNDI membutuhkan pemahaman tentang layanan yang mendasari serta implementasi yang dapat diakses. Misalnya, layanan koneksi database memanggil properti tertentu dan penanganan pengecualian.

Namun, abstraksi JNDI memisahkan konfigurasi koneksi dari aplikasi.

Mari jelajahi Nama dan Konteks , yang berisi fungsionalitas inti JNDI.

2.1. Antarmuka Nama

Name objectName = new CompositeName("java:comp/env/jdbc");

The Nama antarmuka menyediakan kemampuan untuk mengelola nama komponen dan sintaks untuk nama JNDI. Token pertama dari string tersebut mewakili konteks global, setelah itu setiap string yang ditambahkan mewakili sub-konteks berikutnya:

Enumeration elements = objectName.getAll(); while(elements.hasMoreElements()) { System.out.println(elements.nextElement()); }

Output kami terlihat seperti:

java:comp env jdbc

Seperti yang bisa kita lihat, / adalah pembatas untuk sub-konteks Nama . Sekarang, mari tambahkan sub-konteks:

objectName.add("example");

Kemudian kami menguji penambahan kami:

assertEquals("example", objectName.get(objectName.size() - 1));

2.2. Antarmuka Konteks

Konteks berisi properti untuk penamaan dan layanan direktori . Di sini, mari gunakan beberapa kode pembantu dari Spring untuk kenyamanan membangun Konteks :

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); builder.activate();

SimpleNamingContextBuilder Spring membuat penyedia JNDI dan kemudian mengaktifkan pembuatnya dengan NamingManager :

JndiTemplate jndiTemplate = new JndiTemplate(); ctx = (InitialContext) jndiTemplate.getContext();

Terakhir, JndiTemplate membantu kita mengakses InitialContext .

3. JNDI Object Binding dan Lookup

Sekarang kita telah melihat cara menggunakan Nama dan Konteks , mari gunakan JNDI untuk menyimpan Sumber Data JDBC :

ds = new DriverManagerDataSource("jdbc:h2:mem:mydb");

3.1. Mengikat Objek JNDI

Karena kita memiliki konteks, mari ikat objek ke dalamnya:

ctx.bind("java:comp/env/jdbc/datasource", ds);

Secara umum, layanan harus menyimpan referensi objek, data berseri, atau atribut dalam konteks direktori. Itu semua tergantung kebutuhan aplikasi.

Perhatikan bahwa menggunakan JNDI dengan cara ini lebih jarang. Biasanya, JNDI berinteraksi dengan data yang dikelola di luar runtime aplikasi.

Namun, jika aplikasi sudah dapat membuat atau menemukan Sumber Data -nya , mungkin lebih mudah untuk menghubungkannya menggunakan Spring. Sebaliknya, jika sesuatu di luar aplikasi kita mengikat objek di JNDI, maka aplikasi dapat menggunakannya.

3.2. Mencari Objek JNDI

Mari kita lihat Sumber Data kami :

DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");

Dan kemudian mari kita uji untuk memastikan bahwa Sumber Data seperti yang diharapkan:

assertNotNull(ds.getConnection());

4. Pengecualian JNDI Umum

Bekerja dengan JNDI terkadang dapat mengakibatkan pengecualian waktu proses. Berikut ini beberapa yang umum.

4.1. NameNotFoundException

ctx.lookup("badJndiName");

Karena nama ini tidak terikat dalam konteks ini, kami melihat pelacakan tumpukan ini:

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)

Kita harus mencatat bahwa pelacakan tumpukan berisi semua objek yang terikat, yang berguna untuk melacak mengapa pengecualian terjadi.

4.2. NoInitialContextException

Setiap interaksi dengan InitialContext bisa memunculkan NoInitialContextException :

assertThrows(NoInitialContextException.class, () -> { JndiTemplate jndiTemplate = new JndiTemplate(); InitialContext ctx = (InitialContext) jndiTemplate.getContext(); ctx.lookup("java:comp/env/jdbc/datasource"); }).printStackTrace();

Perlu dicatat bahwa penggunaan JNDI ini valid, seperti yang kita gunakan sebelumnya. Namun, saat ini tidak ada penyedia konteks JNDI, dan pengecualian akan diberikan:

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. Peran JNDI dalam Arsitektur Aplikasi Modern

While JNDI plays less of a role in lightweight, containerized Java applications such as Spring Boot, there are other uses. Three Java technologies that still use JNDI are JDBC, EJB, and JMS. All have a wide array of uses across Java enterprise applications.

For example, a separate DevOps team may manage environment variables such as username and password for a sensitive database connection in all environments. A JNDI resource can be created in the web application container, with JNDI used as a layer of consistent abstraction that works in all environments.

This setup allows developers to create and control a local definition for development purposes while connecting to sensitive resources in a production environment through the same JNDI name.

6. Conclusion

Dalam tutorial ini, kami melihat menghubungkan, mengikat, dan mencari objek menggunakan Java Naming and Directory Interface. Kami juga melihat pengecualian umum yang diberikan oleh JNDI.

Terakhir, kami melihat bagaimana JNDI cocok dengan arsitektur aplikasi modern.

Seperti biasa, kode tersedia di GitHub.