Hello! Dina iki kita bakal ngenalake sampeyan JNDI. Ayo goleki apa iku, kenapa perlu, cara kerjane, kepiye carane bisa. Banjur kita bakal nulis tes unit Spring Boot, ing njero kita bakal main karo JNDI iki.
Pambuka. Layanan Jeneng lan Direktori
Sadurunge nyilem menyang JNDI, ayo padha ngerti apa layanan jeneng lan direktori. Conto paling jelas saka layanan kasebut yaiku sistem file ing PC, laptop utawa smartphone. Sistem file ngatur file (cukup aneh). File ing sistem kasebut dikelompokake ing struktur wit. Saben berkas nduweni jeneng lengkap sing unik, contone: C:\windows\notepad.exe. Wigati dicathet: jeneng berkas lengkap minangka path saka sawetara titik root (drive C) menyang file kasebut (notepad.exe). Node penengah ing rantai kasebut yaiku direktori (direktori windows). File ing direktori duwe atribut. Contone, "Didhelikake", "Mung-Waca", lan liya-liyane. Katrangan rinci babagan prasaja kaya sistem file bakal mbantu luwih ngerti definisi jeneng lan layanan direktori. Dadi, layanan jeneng lan direktori minangka sistem sing ngatur pemetaan akeh jeneng menyang akeh obyek. Ing sistem file kita, kita sesambungan karo jeneng file sing ndhelikake obyek-file dhewe ing macem-macem format. Ing layanan jeneng lan direktori, obyek sing dijenengi diatur dadi struktur wit. Lan obyek direktori duwe atribut. Conto liyane saka layanan jeneng lan direktori yaiku DNS (Domain Name System). Sistem iki ngatur pemetaan antarane jeneng domain sing bisa diwaca manungsa (contone, https://javarush.com/) lan alamat IP sing bisa diwaca mesin (contone, 18.196.51.113). Saliyane DNS lan sistem file, ana akeh layanan liyane, kayata:- Lightweight Directory Access Protocol (LDAP) ;
- Layanan penamaan CORBA ;
- Layanan Informasi Jaringan (NIS) ;
- Lan liyane.
JNDI
JNDI, utawa Java Naming and Directory Interface, minangka API Java kanggo ngakses layanan jeneng lan direktori. JNDI minangka API sing nyedhiyakake mekanisme seragam kanggo program Java kanggo sesambungan karo macem-macem layanan jeneng lan direktori. Ing hood, integrasi antarane JNDI lan layanan tartamtu wis rampung nggunakake Service Provider Interface (SPI). SPI ngidini macem-macem layanan jeneng lan direktori disambungake kanthi transparan, ngidini aplikasi Java nggunakake API JNDI kanggo ngakses layanan sing disambungake. Gambar ing ngisor iki nggambarake arsitektur JNDI:Sumber: Oracle Java Tutorials
JNDI. Tegese ing tembung prasaja
Pitakonan utama yaiku: kenapa kita butuh JNDI? JNDI dibutuhake supaya kita bisa njaluk obyek Jawa saka sawetara "Registration" obyek saka kode Jawa kanthi jeneng obyek kaiket kanggo obyek iki. Pratelan ing ndhuwur dipecah dadi tesis supaya akeh tembung sing bola-bali ora mbingungake:- Wekasanipun kita kudu njaluk obyek Jawa.
- Kita bakal entuk obyek iki saka sawetara pendaptaran.
- Ana akeh obyek ing registri iki.
- Saben obyek ing registri iki nduweni jeneng unik.
- Kanggo entuk obyek saka registri, kita kudu menehi jeneng ing panyuwunan kita. Kaya-kaya ngomong: "Mangga paringana apa sing sampeyan duwe jeneng iki lan iki."
- Kita ora mung bisa maca obyek kanthi jeneng saka registri, nanging uga nyimpen obyek ing registri iki ing jeneng tartamtu (piye wae, padha mungkasi munggah ana).
JNDI API
JNDI kasedhiya ing platform Java SE. Kanggo nggunakake JNDI, sampeyan kudu ngimpor kelas JNDI, uga siji utawa luwih panyedhiya layanan kanggo ngakses layanan jeneng lan direktori. JDK kalebu panyedhiya layanan kanggo layanan ing ngisor iki:- Protokol Akses Direktori Ringan (LDAP);
- Arsitektur Broker Panjaluk Objek Umum (CORBA);
- Layanan jeneng Layanan Objek Umum (COS);
- Registry Java Remote Method Invocation (RMI);
- Layanan Jeneng Domain (DNS).
- javax.naming;
- javax.naming.directory;
- javax.naming.ldap;
- javax.naming.event;
- javax.naming.spi.
Jeneng Antarmuka
Antarmuka Jeneng ngidini sampeyan ngontrol jeneng komponen uga sintaks jeneng JNDI. Ing JNDI, kabeh operasi jeneng lan direktori dileksanakake relatif marang konteks. Ora ana oyod sing mutlak. Mulane, JNDI nemtokake InitialContext, sing nyedhiyakake titik wiwitan kanggo operasi jeneng lan direktori. Sawise konteks wiwitan diakses, bisa digunakake kanggo nggoleki obyek lan konteks liyane.Name objectName = new CompositeName("java:comp/env/jdbc");
Ing kode ing ndhuwur, kita nemtokake sawetara jeneng ing ngendi sawetara obyek dumunung (bisa uga ora ana, nanging kita ngetang). Tujuan pungkasan kita yaiku njupuk referensi kanggo obyek iki lan digunakake ing program kita. Dadi, jeneng kasebut kalebu sawetara bagean (utawa token), dipisahake kanthi garis miring. Token kasebut diarani konteks. Sing pisanan mung konteks, kabeh sing sabanjure minangka sub-konteks (sabanjuré diarani subkonteks). Konteks luwih gampang dingerteni yen sampeyan nganggep padha karo direktori utawa direktori, utawa mung folder biasa. Konteks root yaiku folder root. Subkonteks minangka subfolder. Kita bisa ndeleng kabeh komponen (konteks lan subkonteks) saka jeneng tartamtu kanthi mbukak kode ing ngisor iki:
Enumeration<String> elements = objectName.getAll();
while(elements.hasMoreElements()) {
System.out.println(elements.nextElement());
}
Output bakal kaya ing ngisor iki:
java:comp
env
jdbc
Output nuduhake yen token ing jeneng dipisahake saka saben liyane kanthi garis miring (Nanging, kita kasebut iki). Saben token jeneng duwe indeks dhewe. Indeksing token diwiwiti ing 0. Konteks root duwe indeks nol, konteks sabanjure duwe indeks 1, sabanjure 2, etc. Kita bisa entuk jeneng subkonteks kanthi indeks:
System.out.println(objectName.get(1)); // -> env
Kita uga bisa nambah token tambahan (ing pungkasan utawa ing lokasi tartamtu ing indeks):
objectName.add("sub-context"); // Добавит sub-context в конец
objectName.add(0, "context"); // Добавит context в налачо
Dhaptar cara lengkap bisa ditemokake ing dokumentasi resmi .
Konteks Antarmuka
Antarmuka iki ngemot seperangkat konstanta kanggo miwiti konteks, uga sakumpulan cara kanggo nggawe lan mbusak konteks, ngiket obyek menyang jeneng, lan nggoleki lan njupuk obyek. Ayo goleki sawetara operasi sing ditindakake nggunakake antarmuka iki. Tindakan sing paling umum yaiku nggoleki obyek kanthi jeneng. Iki ditindakake kanthi nggunakake metode:Object lookup(String name)
Object lookup(Name name)
bind
:
void bind(Name name, Object obj)
void bind(String name, Object obj)
Object
Operasi invers saka naleni - unbinding obyek saka jeneng, ditindakake kanthi nggunakake metode unbind
:
void unbind(Name name)
void unbind(String name)
Konteks Awal
InitialContext
iku kelas sing makili unsur ROOT saka wit JNDI lan ngleksanakake ing Context
. Sampeyan kudu nggoleki obyek kanthi jeneng ing wit JNDI relatif marang simpul tartamtu. Simpul oyod wit bisa dadi simpul kasebut InitialContext
. Kasus panggunaan khas kanggo JNDI yaiku:
- njaluk
InitialContext
. - Gunakake
InitialContext
kanggo njupuk obyek kanthi jeneng saka wit JNDI.
InitialContext
. Iku kabeh gumantung ing lingkungan ing ngendi program Jawa dumunung. Contone, yen program Java lan wit JNDI mlaku ing server aplikasi sing padha, cukup InitialContext
gampang kanggo njaluk:
InitialContext context = new InitialContext();
Yen ora, njupuk konteks dadi luwih angel. Kadhangkala perlu kanggo ngliwati dhaptar properti lingkungan kanggo miwiti konteks:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
Context ctx = new InitialContext(env);
Conto ing ndhuwur nuduhake salah sawijining cara kanggo miwiti konteks lan ora nggawa beban semantik liyane. Ora perlu nyilem menyang kode kanthi rinci.
Conto nggunakake JNDI ing tes unit SpringBoot
Ing nginggil, kadhawuhaken bilih JNDI saged sesrawungan kaliyan layanan nama lan direktori, perlu wonten SPI (Service Provider Interface), kanthi bantuan integrasi antawisipun Jawi kaliyan jasa penamaan. JDK standar dilengkapi karo sawetara SPI sing beda-beda (kita kadhaptar ing ndhuwur), sing saben-saben ora kapentingan kanggo tujuan demonstrasi. Ngunggahake aplikasi JNDI lan Java ing njero wadhah rada menarik. Nanging, penulis artikel iki minangka wong kesed, supaya kanggo nduduhake cara kerjane JNDI, dheweke milih dalan sing paling ora tahan: mbukak JNDI ing tes unit aplikasi SpringBoot lan ngakses konteks JNDI nggunakake hack cilik saka Spring Framework. Dadi, rencana kita:- Ayo nulis proyek Spring Boot kosong.
- Ayo nggawe tes unit ing proyek iki.
- Ing tes, kita bakal nduduhake nggarap JNDI:
- entuk akses menyang konteks;
- ikatan (ikatan) sawetara obyek ing sawetara jeneng ing JNDI;
- njaluk barang kanthi jeneng (lookup);
- Ayo priksa manawa obyek kasebut ora null.
- JDBC API;
- H2 Ddatabase.
SimpleNamingContextBuilder
. Kelas iki dirancang kanggo gampang ngunggahake JNDI ing tes unit utawa aplikasi mandiri. Ayo nulis kode kanggo entuk konteks:
final SimpleNamingContextBuilder simpleNamingContextBuilder
= new SimpleNamingContextBuilder();
simpleNamingContextBuilder.activate();
final InitialContext context = new InitialContext();
Rong baris kode pisanan bakal ngidini kita miwiti konteks JNDI kanthi gampang mengko. Tanpa wong-wong mau, InitialContext
pangecualian bakal dibuwang nalika nggawe conto javax.naming.NoInitialContextException
:. Penafian. Kelas kasebut SimpleNamingContextBuilder
minangka kelas Deprecated. Lan conto iki dimaksudake kanggo nuduhake carane sampeyan bisa nggarap JNDI. Iki dudu praktik paling apik kanggo nggunakake tes unit JNDI. Iki bisa diarani minangka crutch kanggo mbangun konteks lan nduduhake naleni lan njupuk obyek saka JNDI. Sawise nampa konteks, kita bisa ngekstrak obyek kasebut utawa nggoleki obyek ing konteks kasebut. Ora ana obyek ing JNDI, mula logis yen dilebokake ing kana. Tuladhane, DriverManagerDataSource
:
context.bind("java:comp/env/jdbc/datasource", new DriverManagerDataSource("jdbc:h2:mem:mydb"));
Ing baris iki, kita wis bound obyek kelas DriverManagerDataSource
kanggo jeneng java:comp/env/jdbc/datasource
. Sabanjure, kita bisa njaluk obyek saka konteks kanthi jeneng. Kita ora duwe pilihan kajaba kanggo njaluk obyek sing mung kita sijine, amarga ora ana obyek liyane ing konteks =(
final DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");
Saiki ayo priksa manawa DataSource kita duwe sambungan (sambungan, sambungan utawa sambungan minangka kelas Java sing dirancang kanggo nggarap database):
assert ds.getConnection() != null;
System.out.println(ds.getConnection());
Yen kita nindakake kabeh kanthi bener, output bakal kaya iki:
conn1: url=jdbc:h2:mem:mydb user=
Iku worth ngomong sing sawetara baris kode bisa uncalan pangecualian. Garis ing ngisor iki dibuwang javax.naming.NamingException
:
simpleNamingContextBuilder.activate()
new InitialContext()
context.bind(...)
context.lookup(...)
DataSource
bisa dibuwang java.sql.SQLException
. Ing babagan iki, perlu kanggo nglakokake kode ing njero blok try-catch
, utawa nuduhake ing tandha unit tes sing bisa mbuwang pengecualian. Punika kode lengkap kelas tes:
@SpringBootTest
class JndiExampleApplicationTests {
@Test
void contextLoads() {
try {
final SimpleNamingContextBuilder simpleNamingContextBuilder
= new SimpleNamingContextBuilder();
simpleNamingContextBuilder.activate();
final InitialContext context = new InitialContext();
context.bind("java:comp/env/jdbc/datasource", new DriverManagerDataSource("jdbc:h2:mem:mydb"));
final DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");
assert ds.getConnection() != null;
System.out.println(ds.getConnection());
} catch (SQLException | NamingException e) {
e.printStackTrace();
}
}
}
Sawise mbukak tes, sampeyan bisa ndeleng log ing ngisor iki:
o.s.m.jndi.SimpleNamingContextBuilder : Activating simple JNDI environment
o.s.mock.jndi.SimpleNamingContext : Static JNDI binding: [java:comp/env/jdbc/datasource] = [org.springframework.jdbc.datasource.DriverManagerDataSource@4925f4f5]
conn1: url=jdbc:h2:mem:mydb user=
GO TO FULL VERSION