Domanda

È una cattiva idea usare il concatenamento delle eccezioni quando si generano RemoteExceptions? Abbiamo un server RMI che fa qualcosa del genere:

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

Ricevo UnmarshallException causata da ClassNotFoundException nel mio client. Tra i lati positivi, si scopre che CustomException stessa viene esportata. Sfortunatamente, un'altra eccezione all'interno di questo ragazzo NON viene esportata, ed è qui che entra in gioco ClassNotFoundException. Penso che la gerarchia sia qualcosa del genere:

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

Il problema che vedo è che anche se possiamo garantire l'esportazione di CustomException, non possiamo garantire che vi siano eccezioni di livello inferiore.

Mi sto proponendo MAI di utilizzare il concatenamento delle eccezioni con RemoteExceptions per questo motivo. Invece, penso che dovrei probabilmente registrare la traccia dello stack sul lato server e lanciare una semplice RemoteException vanilla senza & Quot; cause & Quot; eccezione incatenata ad esso. Qualcuno ha affrontato questa situazione prima?

È stato utile?

Soluzione

Invece di includere CustomException in RemoteException, è possibile modificare l'interfaccia remota in questo modo:

interface Foo extends Remote {

  Object doSomething() throws CustomException, RemoteException;

}

Il principio qui è che solo il runtime RMI dovrebbe generare RemoteExceptions; segnalano qualche errore nel remoting, non nella logica dell'applicazione. In effetti, le implementazioni concrete non hanno nemmeno bisogno di dichiarare RemoteException.

Ma questo non gestisce il caso in cui il tuo servizio sta rilevando un'eccezione da alcune librerie di terze parti, ma non vuole esporlo in una clausola di lancio.

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) ?
  }
}

In questo caso, ti consiglio di non creare un " astrazione che perde " ;, in cui verrebbe creata una dipendenza in un client che altrimenti non avrebbe bisogno di conoscere quella libreria di terze parti .

Normalmente, la registrazione dei lanci e è una cattiva pratica, perché lo stesso errore viene registrato ripetutamente. Ma in questo caso, penso che sia giustificato, poiché l'eccezione generata viene trasportata al client; può essere utile registrarlo sia sul client che sul server. Quindi il blocco catch finisce così:

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

In questo modo, la dipendenza ThirdPartyException è limitata al server, i registri del server contengono informazioni specifiche sull'implementazione appropriate e l'errore viene correttamente segnalato al client.

Altri suggerimenti

Acquisiamo il messaggio + traccia dello stack intero dall'eccezione di origine e lo passiamo come contenuto dell'eccezione remota. In questo modo ottieni tutti i dettagli dello stack, ma non devi preoccuparti che QUALUNQUE delle eccezioni interne non sia serializzabile.

Non si sa mai quali altri oggetti potrebbero trovarsi all'interno di altre terze parti (o anche il proprio " first party " eccezioni personalizzate!)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top