使用 RMI 链接异常不是个好主意吗?
抛出 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以像这样修改远程接口,而不是将 CustomException 包装在 RemoteException 中:
这里的原则是只有 RMI 运行时才应该引发 RemoteException; 它们表示远程处理失败,而不是应用程序逻辑失败。 事实上,具体实现甚至不需要声明
RemoteException
。但是,这不能处理您的服务从某些第三方库捕获异常,但又不想在 throws 子句中公开该异常的情况。
在这种情况下,我建议您不要创建“泄漏抽象”,即在客户端中创建依赖项,否则无需了解该第三方库。
通常,记录和抛出是不好的做法,因为相同的错误会被重复记录。 但在这种情况下,我认为这是合理的,因为抛出的异常被传输到客户端; 在客户端和服务器上记录它可能会很有用。 因此,catch 块最终看起来像这样:
这样,ThirdPartyException 依赖项仅限于服务器,服务器日志包含适当的特定于实现的信息,并且错误会正确报告给客户端。
Rather than wrapping CustomException in RemoteException, you might modify your remote interface like this:
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.
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:
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.
我们从源异常中捕获消息+整个堆栈跟踪,并将其作为远程异常的内容传递。 这样您就可以获取所有堆栈详细信息,但不必担心任何不可序列化的内部异常。
您永远不知道其他第三方中可能存在哪些其他对象(甚至您自己的“第一方”自定义异常!)
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!)