2008-12-08 33 views
2

拋出RemoteExceptions時使用異常鏈接是不是一個好主意?我們有做這樣的事情的RMI服務器:用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,並且沒有「cause」異常鏈接到它。有人以前處理過這種情況嗎?

+0

的【什麼是鏈接異常的優勢(HTTP可能的複製(甚至你自己的「第一方」自定義異常!):// stackoverflow.com/questions/5020876/what-is-the-advantage-of-chained-exceptions) – Raedwald 2016-01-20 18:29:51

回答

5

而不是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依賴僅限於服務器,服務器日誌包含適當的執行相關的信息,並且該錯誤被正確地報告給客戶端。

+0

但這意味着customexception也是可序列化/可編組的,是正確的嗎?這是海報的原始問題。 – 2008-12-08 23:07:44

+0

不,問題指出CustomException被導出,但是鏈接到它的一些例外不是。但是,如果您使用我概述的方法,客戶端顯然依賴於CustomException(它是接口API的一部分),並且它必須在客戶端可用。 – erickson 2008-12-08 23:26:02

3

我們從源異常中捕獲消息+整個堆棧跟蹤,並將其作爲遠程異常的內容傳遞。這樣你就可以得到所有的堆棧細節,但是你不必擔心任何內部異常都是不可序列化的。

你永遠不知道還有什麼其他的對象可能是一些其他第三方內