Java 이름 지정 및 디렉토리 인터페이스 개요

1. 소개

JNDI (Java Naming and Directory Interface) 는 이름 지정 및 / 또는 디렉토리 서비스를 Java API로 일관되게 사용합니다. 이 인터페이스는 개체 바인딩, 개체 조회 또는 쿼리 및 동일한 개체의 변경 사항 감지에 사용할 수 있습니다.

JNDI 사용법에는 지원되는 이름 지정 및 디렉토리 서비스의 다양한 목록이 포함되어 있지만이 튜토리얼에서는 JNDI의 API를 탐색하는 동안 JDBC에 중점을 둘 것입니다.

2. JNDI 설명

JNDI이있는 모든 작업은 필요 기본 서비스에 대한 이해 뿐만 아니라 접근 구현을. 예를 들어, 데이터베이스 연결 서비스는 특정 속성 및 예외 처리를 요청합니다.

그러나 JNDI의 추상화는 애플리케이션에서 연결 구성을 분리합니다.

JNDI의 핵심 기능이 포함 된 NameContext를 살펴 보겠습니다 .

2.1. 이름 인터페이스

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

이름 인터페이스는 JNDI 이름에 대한 구성 요소 이름과 구문을 관리 할 수있는 기능을 제공합니다. 문자열의 첫 번째 토큰은 전역 컨텍스트를 나타내고 추가 된 각 문자열은 다음 하위 컨텍스트를 나타냅니다.

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

출력은 다음과 같습니다.

java:comp env jdbc

보시다시피 /이름 하위 컨텍스트 의 구분 기호입니다 . 이제 하위 컨텍스트를 추가해 보겠습니다.

objectName.add("example");

그런 다음 추가를 테스트합니다.

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

2.2. 컨텍스트 인터페이스

컨텍스트 에는 이름 지정 및 디렉터리 서비스에 대한 속성이 포함 됩니다. 여기에서는 편의를 위해 Context 를 빌드하기 위해 Spring의 일부 도우미 코드를 사용합시다 .

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

Spring의 SimpleNamingContextBuilder 는 JNDI 공급자를 생성 한 다음 NamingManager 를 사용하여 빌더를 활성화합니다 .

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

마지막으로, JndiTemplate 은 우리가 InitialContext에 접근하도록 도와줍니다 .

3. JNDI 개체 바인딩 및 조회

NameContext 를 사용하는 방법을 살펴 보았 으므로 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 을 throw 할 수 있습니다 .

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의 역할

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

이 튜토리얼에서는 Java Naming 및 Directory Interface를 사용하여 객체를 연결, 바인딩 및 조회하는 것을 보았습니다. 또한 JNDI에서 발생하는 일반적인 예외를 살펴 보았습니다.

마지막으로 JNDI가 최신 애플리케이션 아키텍처에 어떻게 적용되는지 살펴 보았습니다.

항상 그렇듯이 코드는 GitHub에서 사용할 수 있습니다.