Question

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:

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

Je reçois une exception UnmarshallException provoquée par une exception ClassNotFoundException sur mon client. Du côté positif, il s'avère que CustomException elle-même est exportée. Malheureusement, une autre exception au fond de ce type n’est PAS exportée, c’est là que la ClassNotFoundException entre en jeu. Je pense que la hiérarchie ressemble à ceci:

RemoteException - > CustomException - & Gt; SQLException - & Gt; NotExportedException

Le problème que je vois est que, même si nous pouvons garantir que CustomException est exportée, nous ne pouvons pas garantir que les exceptions de niveau inférieur le soient.

Je suis enclin à ne JAMAIS utiliser d'exception chaînant avec RemoteExceptions pour cette raison. Au lieu de cela, je pense que je devrais probablement consigner la trace de la pile côté serveur et lancer une exception RemoteException simple et vanille sans & Quot; cause & Quot; exception enchaînée à elle. Quelqu'un a déjà fait face à cette situation?

Était-ce utile?

La solution

Plutôt que d'encapsuler CustomException dans RemoteException, vous pouvez modifier votre interface distante de la manière suivante:

interface Foo extends Remote {

  Object doSomething() throws CustomException, RemoteException;

}

Le principe ici est que seul le runtime RMI devrait lever des exceptions RemoteExceptions; ils signalent une défaillance de la communication à distance, et non de 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 intercepte une exception provenant 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 ne pas créer une & "fuitey abstraction &", dans laquelle une dépendance serait créée dans un client qui n'aurait autrement pas besoin de connaître cette bibliothèque tierce. .

Normalement, il est déconseillé de consigner et en jetant, car la même erreur est consignée à plusieurs reprises. Mais dans ce cas, je pense que cela est justifié, étant donné que l’exception levée est transmise au client; il peut être utile de le consigner à la fois sur le client et sur le serveur. Donc, le bloc de capture finit par ressembler à ceci:

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

De cette manière, la dépendance ThirdPartyException est limitée au serveur, les journaux du serveur contiennent les informations appropriées à l'implémentation et l'erreur est correctement signalée au client.

Autres conseils

Nous capturons le message + la trace de pile entière de l'exception source et nous la transmettons en tant que contenu de l'exception distante. De cette façon, vous obtenez tous les détails de la pile, mais vous n’aurez à vous soucier d’aucune des exceptions internes qui ne soit pas sérialisable.

Vous ne savez jamais quels autres objets pourraient se trouver chez un tiers (ni même vos propres & "; premières parties &"; exceptions personnalisées!)

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top