题
这是个糟糕的主意扔异常RemoteExceptions时使用异常链?我们有做这样的事情的RMI服务器:
public Object doSomething() throws RemoteException
{
try
{
return getData();
}
catch (CustomException ex)
{
throw new RemoteException(ex);
}
}
我越来越引起了我的客户一个ClassNotFoundException UnmarshallException。从积极的一面,事实证明,CustomException本身就是出口。不幸的是,另一个异常内心深处,这家伙不是出口,这是其中的ClassNotFoundException进来我想层次是这样的:
的RemoteException - > CustomException - >的SQLException - > NotExportedException
我看到的问题是,即使我们可以保证CustomException出口,我们不能保证任何下级例外。
我倾向于使用从未有例外,因为这个异常RemoteExceptions链接。相反,我想我大概应该记录在服务器端的堆栈跟踪,并抛出一个普通的,香草的RemoteException没有“原因”异常链接到它。任何人处理这个情况之前?
解决方案
而不是RemoteException的包装CustomException,您可以修改您的远程接口是这样的:
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依赖性被限制到服务器,服务器日志包含适当的执行相关的信息,并且该错误被正确地报告给客户端。
其他提示
我们捕获来自源异常消息+整个堆栈跟踪,并通过该上作为远程异常的内容。这样,你得到所有的堆细节,但你不必担心任何的任何内部的例外是不可序列化的。
您永远不知道还有什么其他的对象可能是一些其他第三方内(甚至是你自己的“第一方”自定义异常!)