2008-12-08 6 views
2

Est-ce une mauvaise idée d'utiliser le chaînage d'exceptions lors du lancement de RemoteExceptions? Nous avons un serveur RMI qui fait quelque chose comme ceci:Mauvaise idée de chaîner des exceptions avec RMI?

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

Je reçois UnmarshallException causé par un ClassNotFoundException dans mon client. Sur le plan positif, il s'avère que CustomException lui-même est exporté. . Malheureusement, une autre exception au fond de ce type est pas exporté, ce qui est où le ClassNotFoundException vient, je pense que la hiérarchie est quelque chose comme ceci:

RemoteException -> CustomException -> SQLException -> NotExportedException

Le problème que je voyez-vous que même si nous pouvons garantir que CustomException est exporté, nous ne pouvons pas garantir que les exceptions de niveau inférieur sont.

Je penche vers JAMAIS en utilisant le chaînage d'exception avec RemoteExceptions à cause de cela. Au lieu de cela, je pense que je devrais probablement enregistrer la trace de la pile du côté serveur et lancer une exception RemoteException simple, sans exception "cause". Quelqu'un a-t-il déjà fait face à cette situation?

+0

double possible de [Quel est l'avantage des exceptions enchaînées] (http (ou même vos propres « première partie » exceptions personnalisées!): // stackoverflow.com/questions/5020876/what-is-the-advantage-of-chained-exceptions) – Raedwald

Répondre

5

Plutôt que d'envelopper CustomException dans RemoteException, vous pouvez modifier votre interface distante comme ceci:

interface Foo extends Remote { 

    Object doSomething() throws CustomException, RemoteException; 

} 

Le principe ici est que seul le moteur d'exécution RMI doit être élever RemoteException; ils signalent une défaillance dans la communication à distance, pas dans la logique de l'application. En fait, les implémentations concrètes n'ont même pas besoin de déclarer le RemoteException. Mais, cela ne gère pas le cas où votre service attrape une exception d'une bibliothèque tierce, mais ne veut pas l'exposer dans une clause 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) ? 
    } 
} 

Dans ce cas, je vous recommande de créer pas une « abstraction qui fuit », où une dépendance serait créé dans un client qui aurait autrement pas besoin de savoir sur cette bibliothèque tiers.

Normalement, la consignation et est une mauvaise pratique, car la même erreur est enregistrée plusieurs fois. Mais dans ce cas, je pense que c'est justifié, puisque l'exception levée est transportée au client; Il peut être utile de l'enregistrer sur le client et le serveur. Ainsi, le bloc catch finit par ressembler à ceci:

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

De cette façon, la dépendance ThirdPartyException est limitée au serveur, les journaux de serveur contiennent des informations spécifiques à la mise en œuvre appropriée, et l'erreur est signalée correctement au client.

+0

mais cela implique que la customexception est également sérialisable/marshallable, correct? qui est la question originale de l'affiche. –

+0

Non, la question indique que CustomException est exporté, mais certaines exceptions chaînées ne le sont pas. Cependant, si vous utilisez l'approche que je décris, le client dépend clairement de CustomException (il fait partie de l'interface API), et il devrait être disponible sur le client. – erickson

3

Nous capturons le message + la trace de pile entière de l'exception source et la transmettons comme contenu de l'exception distante. De cette façon, vous obtenez tous les détails de la pile, mais vous n'avez pas à vous soucier que l'une quelconque des exceptions internes soit non sérialisable.

Vous ne savez jamais ce que d'autres objets pourraient être à l'intérieur d'un autre tiers

+0

C'est exactement ce que j'ai fait. Cela fonctionne bien et aucun problème de dépendance. –