使用 RMI 链接异常不是个好主意吗?

发布于 2024-07-10 03:44:53 字数 741 浏览 7 评论 0原文

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

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

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

RemoteException -> 自定义异常 -> SQLException ->; NotExportedException

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

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

Is it a bad idea to use exception chaining when throwing RemoteExceptions? We have an RMI server that does something like this:

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

I'm getting UnmarshallException caused by a ClassNotFoundException in my client. On the plus side, it turns out that CustomException itself IS exported. Unfortunately, another exception deep inside this guy is NOT exported, which is where the ClassNotFoundException comes in. I think the hierarchy is something like this:

RemoteException -> CustomException -> SQLException -> NotExportedException

The problem I see is that even though we can guarantee that CustomException is exported, we can't guarantee that any lower level exceptions are.

I'm leaning towards NEVER using exception chaining with RemoteExceptions because of this. Instead, I think I should probably log the stack trace on the server side and throw a plain, vanilla RemoteException with no "cause" exception chained to it. Anyone dealt with this situation before?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

彼岸花似海 2024-07-17 03:44:53

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

interface Foo extends Remote {

  Object doSomething() throws CustomException, RemoteException;

}

这里的原则是只有 RMI 运行时才应该引发 RemoteException; 它们表示远程处理失败,而不是应用程序逻辑失败。 事实上,具体实现甚至不需要声明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 依赖项仅限于服务器,服务器日志包含适当的特定于实现的信息,并且错误会正确报告给客户端。

Rather than wrapping CustomException in RemoteException, you might modify your remote interface like this:

interface Foo extends Remote {

  Object doSomething() throws CustomException, RemoteException;

}

The principle here is that only the RMI runtime should be raising RemoteExceptions; they signal some failure in the remoting, not in the application logic. In fact, the concrete implementations don't even need to declare the RemoteException.

But, that doesn't handle the case where your service is catching an exception from some third-party library, but doesn't want to expose that in a throws clause.

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) ?
  }
}

In this case, I recommend that you not create a "leaky abstraction", where a dependency would be created in a client that would otherwise have no need to know about that third-party library.

Normally, logging and throwing is bad practice, because the same error gets logged repeatedly. But in this case, I think it's justified, since the thrown exception is transported to the client; it may be useful to log it both at the client and server. So the catch block ends up looking like this:

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

This way, the ThirdPartyException dependency is limited to the server, the server logs contain appropriate implementation-specific information, and the error is correctly reported to the client.

一桥轻雨一伞开 2024-07-17 03:44:53

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

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

We capture the message + entire stack trace from the source exception and passed that on as the remote exception's contents. That way you get all of the stack details, but you don't have to worry about any of ANY of the internal exceptions being non serializable.

You never know what other objects might be inside some other third party (or even your own "first party" custom exceptions!)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文