Excepciones Seguras De Deserializar

De Dos Ideas.
Saltar a: navegación, buscar

Cuando se expone un método para ser invocado en forma remota, por ejemplo en un EJB, puede suceder que tire una excepción como respuesta a la invocación como consecuencia de algún error durante la ejecución. Esta excepción será serializada y pasada por red al método que realizó la invocación.

Cuando llega la excepción del otro lado tiene que volver a hidratarse para lo que es necesario contar con la definición de la clase a deserializar.

Con un poco de cuidado y haciendo las cosas bien, la clase de la Excepción existirá del lado del cliente. Pero también debemos tener en cuenta que las excepciones suelen tener anidada la causa que las produjo (otra excepción) y la causa puede tener anidada a su vez otra causa y así sucesivamente hasta llegar a la raíz del problema que originó el fallo.

Todas las clases de la cadena de causas deben estar presente del lado del cliente que invoca el método remoto ya que intentará rehidratar toda la cadena.

A veces, por alguna razón u otra, puede ser que no tengamos disponible las excepciones de alguna parte de la cadena en el cliente. Este ejemplo muestra como reemplazar las excepciones de la cadena por excepciones que estamos seguros que pueden ser hidratadas nuevamente.

En el método que se invocará remotamente

public class Xxx {

   public void metodoRemoto() throws RemoteException {
       try {
          ...
          todo el funcionamiento debe pasar dentro del try
          para atajar cualquier excepcion que pueda pasar
       } catch (Exception e) {
          //se relanza una excepcion a la que se le reemplaza toda la 
          //cadena de causas por RuntimeExceptions.
          throw HidratacionSegura.asegurarComoRuntime(e);
       }
   }

}


public class SafeHidratableException {

public static RuntimeException secureAsRuntime(Throwable t) {

//Acepta parametro nulo y devuelve nulo en tal caso para soportar recursividad sobre las causas //sin necesidad de investigar si la causa en nula. if (t == null) { return null; }

//Toma la causa de t y la asegura como RuntimeException llamando a este mismo metodo //en forma recursiva. La recursividad se corta cuando la causa es nula. RuntimeException safeCause = secureAsRuntime(t.getCause());

//Toma el mensaje de T y le agrega cual fue la clase original de la excepcion que se esta asegurando la deserializacion. String message = "[SafeHidratable for " + t.getClass().getName() + "] " + t.getMessage();

//Construye una runtime exception que tiene el nombre de la excepcion original, el mensaje original y la causa //asegurada. RuntimeException safeException = new RuntimeException(message, safeCause);

//Copia el stackTrace safeException.setStackTrace(t.getStackTrace());

//devuelve T en forma de Runtime. A esta altura todas las causas ya fueron aseguradas tambien. return safeException;

}

}