2

抛出 RemoteExceptions 时使用异常链接是不是一个坏主意?我们有一个 RMI 服务器,它执行以下操作:

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

我收到 UnmarshallException 是由我的客户端中的 ClassNotFoundException 引起的。从好的方面来说,事实证明 CustomException 本身是导出的。不幸的是,这个人内心深处的另一个异常没有被导出,这就是 ClassNotFoundException 进来的地方。我认为层次结构是这样的:

RemoteException -> CustomException -> SQLException -> NotExportedException

我看到的问题是,即使我们可以保证导出 CustomException,我们也不能保证任何较低级别的异常。

因此,我倾向于从不使用 RemoteExceptions 的异常链接。相反,我认为我可能应该在服务器端记录堆栈跟踪,并抛出一个普通的、普通的 RemoteException,没有“原因”异常链接到它。以前有人处理过这种情况吗?

4

2 回答 2

5

您可以像这样修改远程接口,而不是将 CustomException 包装在 RemoteException 中:

interface Foo extends Remote {

  Object doSomething() throws CustomException, RemoteException;

}

这里的原则是只有 RMI 运行时应该引发 RemoteExceptions;它们表示远程处理中的一些故障,而不是应用程序逻辑中的一些故障。事实上,具体的实现甚至不需要声明RemoteException.

但是,这并不能处理您的服务从某个第三方库捕获异常但又不想在 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) ?
  }
}

在这种情况下,我建议您不要创建“泄漏抽象”,其中将在客户端中创建依赖项,否则无需了解该第三方库。

通常,记录抛出是不好的做法,因为会重复记录相同的错误。但在这种情况下,我认为这是有道理的,因为抛出的异常被传输到客户端;在客户端和服务器上都记录它可能很有用。所以 catch 块最终看起来像这样:

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

这样,ThirdPartyException 依赖仅限于服务器,服务器日志包含适当的特定于实现的信息,并且错误被正确报告给客户端。

于 2008-12-08T23:05:40.687 回答
3

我们从源异常中捕获消息 + 整个堆栈跟踪,并将其作为远程异常的内容传递。这样您就可以获得所有堆栈详细信息,但您不必担心任何任何内部异常都是不可序列化的。

您永远不知道其他第三方中可能包含哪些其他对象(甚至您自己的“第一方”自定义异常!)

于 2008-12-08T23:09:34.797 回答