Oversigt over Java Naming og Directory Interface

1. Introduktion

Java Naming and Directory Interface (JNDI) giver konsekvent brug af navngivning og / eller katalogtjenester som en Java API. Denne grænseflade kan bruges til at binde objekter, slå op eller forespørge på objekter samt til at detektere ændringer på de samme objekter.

Mens JNDI-brug inkluderer en forskellig liste over understøttede navngivnings- og katalogtjenester, fokuserer vi i denne vejledning på JDBC, mens vi udforsker JNDIs API.

2. JNDI Beskrivelse

Alt arbejde med JNDI kræver en forståelse af den underliggende tjeneste såvel som en tilgængelig implementering. For eksempel kræver en databaseforbindelsestjeneste specifikke egenskaber og håndtering af undtagelser.

Imidlertid afkobler JNDIs abstraktion forbindelseskonfigurationen fra applikationen.

Lad os udforske Navn og Sammenhæng, som indeholder kernefunktionaliteten i JNDI.

2.1. Navn Interface

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

Det Navn interface giver mulighed for at styre komponentnavne og syntaks for JNDI-navne. Det første token af ​​strengen repræsenterer den globale kontekst, efter at hver tilføjet streng repræsenterer den næste underkontekst:

Optællingselementer = objectName.getAll (); mens (elements.hasMoreElements ()) {System.out.println (elements.nextElement ()); }

Vores output ser ud som:

java: comp env jdbc

Som vi kan se, / er afgrænser for Navn underkontekster. Lad os nu tilføje en underkontekst:

objectName.add ("eksempel");

Derefter tester vi vores tilføjelse:

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

2.2. Sammenhæng Interface

Sammenhæng indeholder egenskaberne til navngivning og katalogtjeneste. Lad os her bruge en hjælpekode fra Spring for nemheds skyld til at opbygge en Sammenhæng:

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

Forårets SimpleNamingContextBuilder opretter en JNDI-udbyder og aktiverer derefter bygherren med NamingManager:

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

Langt om længe, JndiTemplate hjælper os med at få adgang til InitialContext.

3. JNDI-objektbinding og opslag

Nu hvor vi har set, hvordan man bruger Navn og Sammenhæng, lad os bruge JNDI til at gemme en JDBC Datakilde:

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

3.1. Bindende JNDI-objekter

Da vi har en sammenhæng, lad os binde objektet til det:

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

Generelt skal tjenester gemme en objektreference, serialiserede data eller attributter i en katalogkontekst. Det hele afhænger af applikationens behov.

Bemærk, at brug af JNDI på denne måde er mindre almindelig. Typisk grænseflader JNDI med data, der styres uden for applikationens kørselstid.

Men hvis applikationen allerede kan oprette eller finde den Datakilde, kan det være lettere at tilslutte det ved hjælp af Spring. I modsætning hertil, hvis noget uden for vores applikationsbundne objekter i JNDI, så kunne applikationen forbruge dem.

3.2. Slå JNDI-objekter op

Lad os slå op på vores Datakilde:

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

Og så lad os teste for at sikre det Datakilde er som forventet:

assertNotNull (ds.getConnection ());

4. Almindelige JNDI-undtagelser

Arbejde med JNDI kan undertiden resultere i runtime-undtagelser. Her er nogle almindelige.

4.1. NameNotFoundException

ctx.lookup ("badJndiName");

Da dette navn ikke er bundet i denne sammenhæng, ser vi dette stack-spor:

javax.naming.NameNotFoundException: Navn [badJndiName] ikke bundet; 0 bindinger: [] på org.springframework.mock.jndi.SimpleNamingContext.lookup (SimpleNamingContext.java:140) på java.naming / javax.naming.InitialContext.lookup (InitialContext.java:409)

Vi skal bemærke, at stacksporingen indeholder alle bundne objekter, hvilket er nyttigt til at spore, hvorfor undtagelsen opstod.

4.2. NoInitialContextException

Enhver interaktion med InitialContext kan kaste NoInitialContextException:

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

Vi skal bemærke, at denne brug af JNDI er gyldig, som vi brugte den tidligere. Denne gang er der imidlertid ingen JNDI-kontekstudbyder, og en undtagelse vil blive kastet:

javax.naming.NoInitialContextException: Nødvendigt at angive klassenavn i miljø eller systemegenskab eller i en applikationsressourcefil: java.naming.factory.initial på java.naming / javax.naming.spi.NamingManager.getInitialContext (NamingManager.java: 685)

5. JNDI's rolle i moderne applikationsarkitektur

Mens JNDI spiller mindre rolle i lette, containeriserede Java-applikationer såsom Spring Boot, er der andre anvendelser. Tre Java-teknologier, der stadig bruger JNDI, er JDBC, EJB og JMS. Alle har en bred vifte af anvendelser på tværs af Java-virksomhedsapplikationer.

For eksempel kan et separat DevOps-team administrere miljøvariabler såsom brugernavn og adgangskode til en følsom databaseforbindelse i alle miljøer. En JNDI-ressource kan oprettes i webapplikationsbeholderen, hvor JNDI bruges som et lag med ensartet abstraktion, der fungerer i alle miljøer.

Denne opsætning giver udviklere mulighed for at oprette og kontrollere en lokal definition til udviklingsformål, mens de opretter forbindelse til følsomme ressourcer i et produktionsmiljø via det samme JNDI-navn.

6. Konklusion

I denne vejledning så vi tilslutning, binding og opslag af et objekt ved hjælp af Java Naming and Directory Interface. Vi kiggede også på de almindelige undtagelser kastet af JNDI.

Endelig så vi på, hvordan JNDI passer ind i moderne applikationsarkitektur.

Som altid er koden tilgængelig på GitHub.