Si hemos configurado la propiedad de entorno Context.REFERRAL como "throw", toda remisi�n encontrada resultar� en una ReferralException. Una ReferralException contiene informaci�n de remisi�n--informaci�n que describe la remisi�n (como una lista de URLs)-- y un contexto de remisi�n--el contexto al que se refiere la remisi�n.
Aqu� est�n los pasos que normalmente sigue un programa cuando maneja remisiones manualmente:
- Captura la excepci�n.
- Examina la �nformaci�n de remisi�n usando ReferralException.getReferralInfo(). Por ejemplo, pregunt�ndo al usuario si se deber�a seguir la remisi�n.
- Si se va a seguir la remisi�n, obtiene el contexto de remisi�n usando ReferralException.getReferralContext() y llamando al m�todo del contexto original usando los mismos argumentos suministrados a la llamada orginal.
- Si no se va a seguir la remisi�n, llama a ReferralException.skipReferral(). Si este m�todo devuelve true (que significa que hay m�s remisiones que seguir), llama a ReferralException.getReferralContext() para continuar. Cuando llamados a un m�todo sobre el resultado , lanzar� de nuevo una ReferralException para la siguiente remisi�n a procesar. Vuelve al paso 1 para procesarlo. Si el m�todo devuelve false, es que no hay m�s remisiones y ese procedimiento puede terminarse.
Aqu� tenemos un ejemplo.
// Set the referral property to throw ReferralException
env.put(Context.REFERRAL, "throw");
// Create the initial context
DirContext ctx = new InitialDirContext(env);
// Set the controls for performing a subtree search
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Do this in a loop because you don't know how
// many referrals there will be
for (boolean moreReferrals = true; moreReferrals;) {
try {
// Perform the search
NamingEnumeration answer = ctx.search("", "(objectclass=*)", ctls);
// Print the answer
while (answer.hasMore()) {
System.out.println(">>>" + ((SearchResult)answer.next()).getName());
}
// The search completes with no more referrals
moreReferrals = false;
} catch (ReferralException e) {
if (! followReferral(e.getReferralInfo())) {
moreReferrals = e.skipReferral();
}
// Point to the new context
if (moreReferrals) {
ctx = (DirContext) e.getReferralContext();
}
}
}
Para los m�todos que devuelven una enumeraci�n, como Context.list() o DirContext.search(), debemos situar el bloque try/catch para la ReferralException alrededor de la llamada inicial y del bucle while que itera sobre los resultados. Cuando se lanza la ReferralException, la enumeraci�n existente se convierte en no v�lida y debemos re-llamar al m�todo de contexto original y obtener una nueva enumeraci�n. Observa tambi�n, que el bucle exterior encierra tanto la llamada al m�todo sobre el contexto como la iteracci�n sobre los resultados.
�Autentificando en un Contexto Remitido
Por defecto, cuando llamados a ReferralException.getReferralContext(), el m�todo usa las propiedades de entorno del contexto original, incluyendo las propiedades relacionadas con la seguridad, para crear una conexi�n con el servidor remitido. Algunas veces, para examinar la informaci�n de remisi�n podr�amos querer seguir la remisi�n usando una informaci�n de autentificaci�n diferente.
Podemos hacer esto usando ReferralException.getReferralContext(env).
...
} catch (ReferralException e) {
...
env.put(Context.SECURITY_PRINCIPAL, "newuser");
env.put(Context.SECURITY_CREDENTIALS, "newpasswd");
ctx = e.getReferralContext(env);
}
Si falla la autentificaci�n, es decir, getReferralContext(env) lanza una excepci�n, podemos intentarlo primero llamando a ReferralException.retryReferral() y luego repitiendo la llamada a getReferralContext(env) con las propiedades de entorno actualizadas. Si no queremos reintentarlo, llamamos a ReferralException.skipReferral() antes de llamar a getReferralContext(env).
Aqu� tenemos un ejemplo:
...
} catch (ReferralException e) {
if (!ask("Follow referral " + e.getReferralInfo())) {
moreReferrals = e.skipReferral();
} else {
// Get credentials for the referral being followed
getCreds(env);
}
// Do this in a loop in case getReferralContext()
// fails with bad authentication info.
while (moreReferrals) {
try {
ctx = (DirContext)e.getReferralContext(env);
break; // Success: got context
} catch (AuthenticationException ne) {
if (ask("Authentication failed. Retry")) {
getCreds(env);
e.retryReferral();
} else {
// Give up and go on to the next referral
moreReferrals = e.skipReferral();
}
} catch (NamingException ne) {
System.out.println("Referral failed: " + ne);
// Give up and go on to the next referral
moreReferrals = e.skipReferral();
}
}
}
En este ejemplo, la llamada a e.getReferralContext(env) est� situada dentro de un bucle para que si falla, pueda reintentarlo usando diferentes credenciales. El ejemplo define un m�todo local, getCreds(), para obtener el nombre y las credenciales desde la Entrada Est�ndar para actualizar la propiedade de entorno, env, que est� siendo utilizada para obtener el contexto remitido. Cuando e.getReferralContext(env) falla, el usuario de la aplicaci�n puede eligir entre volver a intentarlo usando diferentes credenciales o saltarse la remisi�n que falla.
�Pasar Controles de Solicitud a un Contexto Remitido
En la lecci�n Controles y Extensiones puedes encontrar m�s detalles sobre c�mo cambiar controles de solicitud sde un contexto remitido.