JNDI (Java Naming and Directory Interface) es un API para el acceso a diferentes servicios de nombres y directorios de una manera uniforme. Proporciona un mecanismo para enlazar programas Java con, por ejemplo, sistemas de ficheros, recursos de red, recursos de bases de datos o servicios de directorios (LDAP). El API de JNDI permite encontrar objetos y datos registrados en estos servicios y así mismo registrar sus propios objetos y datos para que sean usados por otros usuarios.
JNDI suele ser utilizado para lo siguiente:
Un servicio de nombres proporciona un método para mapear nombres lógicos (por ejemplo, databd) con entidades u objetos (un recurso DataSource, un EJB, JMS, etc.). De esta manera, no tenemos que buscar un determinado objeto, sino que buscaremos su nombre lógico. Pensad cuando trabajábamos con las bases de datos. Obteníamos una conexión a partir de un driver y nos conectábamos a una base de datos en concreto, que estaba alojada en una determinada dirección. Si la base de datos cambiaba de nombre o cambiaba su dirección debíamos reflejar dichos cambios en nuestro código. Si utilizamos JNDI y asociamos un nombre lógico, por ejemplo databd, a un objeto DataSource el objeto DataSource es el que manejará los datos de la conexión con la base de datos. Nuestro código Java accede a JNDI y obtiene una referencia al objeto DataSource asociado con el nombre lógico. Si cambian los parámetros de conexión, debemos cambiar el objeto DataSource, pero no nuestro código Java, puesto que el nombre lógico no ha cambiado.
Vamos a definir un par de conceptos:
JNDI suele tener asociado un árbol. En la siguiente figura se muestra un posible árbol JNDI. Todo árbol tiene un contexto raíz, sin embargo el que se utiliza para trabajar es el contexto inicial. A partir de este contexto podemos acceder a los objetos enlazados con este contexto (representados con un triángulo) o descender a subcontextos (los contextos se representan mediante círculos). De esta forma podemos agrupar objetos y organizarlos a nuestra manera. Dentro de JNDI podemos hacer referencia a subcontextos utilizando el "." como delimitador.
Para acceder al contexto inicial debemos utilizar un código similar al mostrado a continuación:
Context miContexto = null; Hashtable ht = new Hashtable (); ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); ht.put(Context.PROVIDER_URL, "t3://localhost:7001"); miContexto = new InitialContext (ht);
En la primera línea hemos creado un contexto. La tabla Hash creada sirve para pasar unos cuantos parámetros iniciales. El primer parámetro es quién nos va a proporcionar el árbol JNDI, en este caso Weblogic. El segundo parámetro es la URL del servidor que nos proporcionará el árbol. Una vez asignados los parámetros iniciales creamos un contexto inicial. En todo código JNDI debemos capturar la excepción NamingException.
Cuando terminemos de utilizar el contexto debemos cerrarlo llamando al método close de Context.
Para asociar un objeto en el árbol utilizaremos el siguiente código:
Persona persona = new Persona(); miContexto.bind ("objeto persona", persona); // miContexto.rebind ("objeto persona", persona);
Hemos creado un objeto cualquiera, en este caso el objeto persona. Utilizamos el contexto para asociar (bind) el nombre "objeto persona" al objeto. Si utilizamos el método bind y ya existe una asociación con este nombre en el árbol, se producirá una excepción. Por ello se puede utilizar la llamada al método rebind que, caso de existir, reemplaza la asociación anterior.
También podemos crear subcontextos para organizar mejor nuestra información. Para crear un subcontexto podemos utilizar el siguiente código:
Context subcontexto = miContexto.createSubContext ("empleados"); Persona persona = new Persona(); subcontexto.bind ("contable", persona);
Hemos creado un subcontexto enlazado con el contexto inicial y dentro de ese subcontexto hemos asociado un objeto.
Por último, queda recuperar un objeto dentro de un contexto. El siguiente código devuelve el objeto introducido en el ejemplo anterior. Observad que es necesario realizar una conversión al objeto que esperamos que se devuelva.
Persona pers = (Persona) miContexto.lookup ("empleados/contable");
Weblogic gestiona un árbol JNDI propio, donde las aplicaciones pueden asociar objetos para que puedan ser utilizados por otras aplicaciones. Podemos ver el árbol JNDI de un determinado servidor. Para ello pinchamos con el botón derecho sobre el servidor seleccionado y pinchamos en el opción View JNDI tree.
Se nos abrirá una nueva ventana que nos mostrará el árbol JNDI. Esta ventana es muy similar a la consola, puesto que está dividida en dos y tiene un applet en la parte izquierda. El applet muestra el árbol y podemos movernos por él para ver los objetos presentes. En la figura se muestra dos objetos, DSJ2EEBD y J2EEDSTX, que son dos fuentes de datos a las que tendremos acceso mediante JNDI.
Algunas veces se hace necesario el uso de clases para realizar ciertas tareas tanto en el arranque como en la parada de los servidores. Un posible ejemplo son las asociaciones que se han creado en el árbol JNDI dentro de WebLogic. Una vez que paremos los servidores estas asociaciones no persisten. Podemos hacer uso de clases que carguen estas asociaciones y que las almacenen cuando paremos los servidores. Para utilizar una clase de arranque o parada pinchamos en el icono Startup & Shutdown y creamos una clase nueva. Debemos especificar el identificador de la clase (elegido de forma arbitraria) y el nombre de la clase. Tened en cuenta que la clase debe estar incluida en el classpath