Programación en castellano Añadir una dirección | Buscador | Cursos | Artículos | Foros | Formación

Sistema de Nombrado en Java (JNDI) [Parte I]
Autor: Sun
Traductor: Juan Antonio Palos (Ozito)


En esta página:


Registro de Oyentes

Para recibir notificaciones de eventos, un oyente se registra con una fuente de evento. En JNDI, las fuentes de eventos implementan los interfaces EventContext o EventDirContext.

Para obtener una fuente de eventos, debemos buscarla usando el servicio de nombres/directorios. Es decir, realizamos un lookup() sobre un objeto que fuerce el resultado a un EventContext o EventDirContext.

Si el contexto soporta o no estos dos interfaces es opcional. Un contexto que no soporte ninguno de ellos no soportará la notificación de eventos.

Aquí tenemos un ejemplo que busca un nombre desde el contexto inicial y lo fuerza a un EventDirContext.

// Get the EventDirContext for registering the listener
EventDirContext ctx = (EventDirContext)
    (new InitialDirContext(env).lookup("ou=People"));

Para obtener una fuente de evento para el propio contexto inicial, usamos un string vacío como argumento para lookup(). Aquí tenemos un ejemplo.

// Get the EventDirContext for registering the listener
EventDirContext ctx = (EventDirContext)
    (new InitialDirContext(env).lookup(""));

EventContext se ha pensado para aplicaciones que pueden nombrar al objeto interesado. Registramos un oyente para recibir notificaciones usando EventContext.addNamingListener().

Aquí tenemos un ejemplo que registra un NamespaceChangeListener con un contexto.

// Get the EventContext for registering the listener
EventContext ctx = (EventContext)
    (new InitialContext(env).lookup("ou=People"));

// Create the listener
NamingListener listener = new SampleNCListener("nc1");

// Register the listener for namespace change events
ctx.addNamingListener("ou=Objects,cn=Rosanna Lee", 
    EventContext.ONELEVEL_SCOPE, listener);

Cuando ejecutemos este ejemplo, esperará un minuto para que el programa principal (el oyente) pueda recibir notificaciones sobre un thread que se ha creado.

Fuente y Ámbito

Al objeto nombrado por el parámetro name de addNamingListener() se le llama fuente. El segundo parámetro especificado es el ámbito.

El ámbito especifica si el oyente recibe notificaciones de uno de los siguientes.

Aquí tenemos un ejemplo  que añade oyentes usando la misma fuente pero tres ámbitos diferentes.

// Get the EventContext for registering the listener
EventContext ctx = (EventContext)
    (new InitialContext(env).lookup("ou=People"));

String target = ...;

// Create the listeners
NamingListener oneListener = new SampleListener("ONELEVEL");
NamingListener objListener = new SampleListener("OBJECT");
NamingListener subListener = new SampleListener("SUBTREE");

// Register the listeners by using different scopes
ctx.addNamingListener(target, EventContext.ONELEVEL_SCOPE, oneListener);
ctx.addNamingListener(target, EventContext.OBJECT_SCOPE, objListener);
ctx.addNamingListener(target, entContext.SUBTREE_SCOPE, subListener);

Después de registrar los oyentes, este programa crea un thread que hace cambios en el espacio de nombres del servidor LDAP. Hace cambios en la fuene, en el hijo de la fuene y en el nieto de la fuene. El oyente registrado para el ámbito del objeto recibirá las dos notificaciones de cambios aplicados a la fuente. El oyente registrado para el ámbito de un nivel no recibirá estás dos notificaciones pero recibirá las notificaciones para los cambios aplicados a los hijos. El oyente registrado para el ámbito del subárbol recibirá las notificaciones de todos los cambios.

Registrando Errores

addNamingListener() puede lanzar una NamingException cuando encuentra un error mientras registra el oyente. Sin embargo, no hay garantía de que los datos suministrados se verifiquen inmediatamente en el momento del registro. Por ejemplo, algunas verificaciones podrían requerir posiblemente interacción con el servidor. Cuando en estos casos ocurre un error, el proveedor de servicios llamará al método namingExceptionThrown() del oyente para notificarle el problema. Por lo tanto la aplicación debe estar preparada para manejar el error sin importarle si ocurre en el momento del registro o asíncronamente en el código del oyente.

Fuentes no Existentes

Algunos servicos/proveedores de servicios podrían permitir el registro de fuentes no existentes. Es decir, en el ejemplo anterior, la entrada llamada target podría no existir necesariamente en el momento de llamar a addNamingListener().

Para chequear si esta característica está soportada, usamos targetMustExist().

Aquí tenemos un ejemplo.

// Get the event context for registering the listener
EventContext ctx = (EventContext)new InitialContext(env).lookup("");

// Create the listener
NamingListener listener = new MyListener();
String target = ...;

// Check whether the object exists so that you don't wait
// forever for nonexistent object
if (!ctx.targetMustExist()) {
    // Check that the object exists before continuing
    // If lookup fails, exception will be thrown and 
    // you would skip registration
    ctx.lookup(target);
}

// Register the listener
ctx.addNamingListener(target, EventContext.ONELEVEL_SCOPE, listener);

Este ejemplo no quiere registrase para un objeto ObjectChangeListener que no exista, por eso primero chequea si el contexto requiere que el objeto exista. Si el contexto no lo requiere, el programa realiza un lookup().

El ejemplo también usa un oyente que implementa NamespaceChangeListener para que podamos detectar cuando el objeto ha desaparecido, en qué punto el oyente se lo notifica al usuario y se auto des-registra.

public void objectRemoved(NamingEvent evt) {
    System.out.println(">>> removed: " + evt.getOldBinding().getName());
    deregisterSelf(evt.getEventContext());
}
private void deregisterSelf(EventContext ctx) {
    System.out.println("Deregistering listener...");
    synchronized (ctx) {
	try {
	    ctx.removeNamingListener(this);
	} catch (NamingException e) {
	    System.out.println("Listener removal problem: " + e);
	}
    }
}

Usar Filtros de Búsqueda

Si queremos ser más selectivos sobre los objetos en los que estamos interesados, podemos usar un filtro de búsqueda. El inteface EventDirContext contiene sobrecargas de addNamingListener() que aceptan filtros de búsqueda, de la misma forma que lo hacen los métodos de búsqueda del interface DirContext.

Aquí tenemos un ejemplo que registra interés sólo en objetos que tengan la clase de objeto "javaobject".

// Get the EventDirContext for registering the listener
EventDirContext ctx = (EventDirContext)
    (new InitialDirContext(env).lookup("ou=People"));

// Create the listener
NamingListener listener = new SampleNCListener("nc1");

// Set up the search constraints
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
	    
// Register the listener for namespace change events for
// entries identified using a search filter.
// In this example, register interest in namespace changes to
// objects that have the object class "javaobject".
ctx.addNamingListener("cn=Rosanna Lee", "(objectclass=javaobject)", 
    constraints, listener);

El filtro sólo se aplica a los objetos existentes y aquellos que empiecen a existir después del registro.

Des-registro

Un oyente registrado se convierte en des-registrado de una estas formas.

  • Cuando se llama a Context.close() sobre la fuente del evento, cualquier oyente registrado será automáticamente des-registrado.
  • Cuando un oyente recibe una notificación de error mediante namingExceptionThrown(), es des-registrado automáticamente.
  • Cuando un oyente es eliminado explícitamente mediante una llamada a EventContext.removeNamingListener(), es des-registrado.

En la sección Fuentes no Existentes puedes ver un ejemplo de des-registro.


Principio Página
© 1999-2002, Programación en castellano, s.l.
Contacto - Datos legales

ReD Internet: Hospedaje Web | envio sms gratis | Salvapantallas | Fondos de Escritorio, famosas | melodias moviles gratis| Gratis