Pregunta

¿Es una mala idea usar el encadenamiento de excepciones al lanzar RemoteExceptions? Tenemos un servidor RMI que hace algo como esto:

public Object doSomething() throws RemoteException
{
    try
    {
        return getData();
    }
    catch (CustomException ex)
    {
        throw new RemoteException(ex);
    }
}

Recibo UnmarshallException causada por una ClassNotFoundException en mi cliente. En el lado positivo, resulta que CustomException en sí se exporta. Desafortunadamente, otra excepción en el fondo de este tipo NO se exporta, que es donde entra la ClassNotFoundException. Creo que la jerarquía es algo como esto:

RemoteException - > CustomException - & Gt; SQLException - & Gt; NotExportedException

El problema que veo es que, aunque podemos garantizar que se exporta CustomException, no podemos garantizar que existan excepciones de nivel inferior.

Me inclino por NUNCA usar el encadenamiento de excepciones con RemoteExceptions debido a esto. En cambio, creo que probablemente debería registrar el seguimiento de la pila en el lado del servidor y lanzar una RemoteException simple y vainilla sin & Quot; causa & Quot; excepción encadenada a ello. ¿Alguien ha lidiado con esta situación antes?

¿Fue útil?

Solución

En lugar de envolver CustomException en RemoteException, puede modificar su interfaz remota de esta manera:

interface Foo extends Remote {

  Object doSomething() throws CustomException, RemoteException;

}

El principio aquí es que solo el tiempo de ejecución de RMI debe aumentar RemoteExceptions; señalan alguna falla en la comunicación remota, no en la lógica de la aplicación. De hecho, las implementaciones concretas ni siquiera necesitan declarar el RemoteException.

Pero, eso no maneja el caso en el que su servicio está detectando una excepción de alguna biblioteca de terceros, pero no quiere exponer eso en una cláusula throws.

public Object doSomething() throws CustomException {
  try {
    return theirSvc.getData();
  } catch (ThirdPartyException ex) {
    throw new CustomException("Failed to obtain requested data.");
    // or: throw new CustomException("Failed to obtain requested data.", ex) ?
  }
}

En este caso, le recomiendo que no cree una " abstracción con fugas " ;, donde se crearía una dependencia en un cliente que de otro modo no tendría necesidad de conocer esa biblioteca de terceros .

Normalmente, registrar el lanzamiento de y es una mala práctica, porque el mismo error se registra repetidamente. Pero en este caso, creo que está justificado, ya que la excepción lanzada se transporta al cliente; Puede ser útil registrarlo tanto en el cliente como en el servidor. Entonces el bloque catch termina así:

catch (ThirdPartyException ex) {
   String message = "Failed to obtain requested data.";
   log.error(message, ex);
   throw new CustomException(message);
 }

De esta manera, la dependencia de ThirdPartyException se limita al servidor, los registros del servidor contienen información específica de implementación apropiada y el error se informa correctamente al cliente.

Otros consejos

Capturamos el mensaje + el seguimiento completo de la pila de la excepción de origen y lo pasamos como contenido de la excepción remota. De esa manera, obtienes todos los detalles de la pila, pero no tienes que preocuparte de que CUALQUIERA de las excepciones internas no sea serializable.

Nunca se sabe qué otros objetos podrían estar dentro de otro tercero (o incluso su propio " ¡primera parte " excepciones personalizadas!)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top