Zentrales Exception Handling

Hi,

ich mache mir gerade über das Exception Handling bei Java Gedanken und habe mich gefragt, ob es nicht sinnig wäre, in einem größeren Programm die Exceptions zentral zu verwalten, also quasi durch ein oder ein paar Klassen. Jedenfalls würde sowas ja
einem objektoriertierten Konzept näher kommen, als es in jeder Klasse einzeln zu tun.

Hat jemand da einen Vorschlag wie sowas am besten anstellen kann oder vielleicht sogar Erfahrung? Oder gibt es dafür Literatur oder Beispiele?

Das wäre klasse.

ich mache mir gerade über das Exception Handling bei Java
Gedanken und habe mich gefragt, ob es nicht sinnig wäre, in
einem größeren Programm die Exceptions zentral zu verwalten,
also quasi durch ein oder ein paar Klassen. Jedenfalls würde
sowas ja
einem objektoriertierten Konzept näher kommen, als es in jeder
Klasse einzeln zu tun.
Hat jemand da einen Vorschlag wie sowas am besten anstellen
kann oder vielleicht sogar Erfahrung? Oder gibt es dafür
Literatur oder Beispiele?

Ich würde dir gerne meine Meinung dazu schildern, mir ist allerdings nicht ganz klar, worauf du hinauswillst :wink: Was meinst du mit „es in jeder Klasse einzeln zu tun“? Kannst du deine Idee etwas konkreter formulieren?

Danke
Bruno

Hi.

Was
meinst du mit „es in jeder Klasse einzeln zu tun“? Kannst du
deine Idee etwas konkreter formulieren?

Also, ich will es mal versuchen. Allerdings so super konkret ist meine Vorstellung auch noch nicht, sonst hätte ich sie ja auch schon realisiert anstatt hier eine Frage zu posten.
Also mal ein Beispiel: Der Konstruktor der Klasse FileReader wirft eine FileNotFoundException, wenn er das File, was er mitbekommt nicht findet. Jetzt willst du ja nicht, daß danach alles abstürtz, also fängst du die Exception sagst dem Progi, was es tun soll, wenn es das File nicht findet, also in etwa so:

try {
FileReader fr = new FileReader(testfile.txt);
}
catch (FileNotFoundException) {
System.out.println(„Ubs ein Fehler beim Einlesen, das File kann nicht gefunden werden“);
}

Diese Fehlerbehandlung mache ich nun in der Klasse, in der ich auch den FileReader brauche. Ich hatte nun die wage Idee, ob es möglich ist, das irgendwie zu zentralisieren, also diese Exception zu fangen und dann an eine andere Klasse weiterzureichen und dort zu bestimmen was nun sein soll. Ich hab mich gefragt, wie genau geht sowas, geht sowas überhaupt und vor allem, macht sowas Sinn ??

Ich hoffe, daß erklärt es etwas besser.

Viele Grüße

Nora

Sowas macht IMHO definitiv Sinn. Vor allem in größeren Serverapplikationen wird die Fehlerbehandlung oft recht aufwendig, da sollte man das auf jeden Fall zentral machen.

Die zentrale Fehlerbehandlung kann natürlich nicht bestimmen was an dem Ort an dem der Fehler passiert ist geschehen soll, aber sie kann den Fehler in Logfiles schreiben, an irgendwelche Systemüberwachungsprogramme melden etc. etc.

Wie man es am besten konkret realisiert hängt von der Anwendung ab. Ich verwende im Moment z. B. ein Interface das eine Methode definiert die die Fehlerbehandlung übernimmt.

Beim Starten der Anwendung wird aus der Konfiguration die Klasse die dafür verwendet werden soll gelesen und dann instanziert und Fehler werden dann immer an diese Klasse übergeben. Dann ists auch schön flexibel.

Grüße, Robert

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Diese Fehlerbehandlung mache ich nun in der Klasse, in der ich
auch den FileReader brauche. Ich hatte nun die wage Idee, ob
es möglich ist, das irgendwie zu zentralisieren, also diese
Exception zu fangen und dann an eine andere Klasse
weiterzureichen und dort zu bestimmen was nun sein soll. Ich
hab mich gefragt, wie genau geht sowas, geht sowas überhaupt
und vor allem, macht sowas Sinn ??

Gehen tut alles :wink: Also bei der Arbeit in einem Projekt machen wir das genauso. Es gibt einen eigenen Exception Typ in unserem Projekt, der dafür verwendet wird und den quasi fast alle Klassen schmeissen können (throws SoundsoException).

Dann fängst du in deiner Methode den Fehler ab und schmeisst eine neue raus. Du kannst dabei bei deiner Exception auch die tatsächliche als Konstruktorparameter reingeben, falls du sie doch noch aussen irgendwie brauchst.

Ob es wirklich Sinn macht weiss ich nicht, aber es wird zumindest mal bei uns so gemacht und nur just 4 fun ist das auch nicht, du hast da eben etwas mehr Kontrolle was eigentlich am Ende alles rausfliegen kann an Exceptions…

Könnte dir aber auf Anhieb auch nicht konkret sagen wieso die andere Lösung schlechter sein sollte.

Gruß
Bruno

Hi,

Beim Starten der Anwendung wird aus der Konfiguration die
Klasse die dafür verwendet werden soll gelesen und dann
instanziert und Fehler werden dann immer an diese Klasse
übergeben. Dann ists auch schön flexibel.

Das gleiche habe ich im Prinzip mit einem Logger gemacht. Ich habe ein Interface, daß einen Logger an sich definiert und einen LogManager. Letzterer liest auch aus einer Conf-Datei aus, welcher Logger genommen werden soll (also einer der auf die GUI loggt oder in ein Datei oder ein System.out.println) und adressiert alle LogMessages an den richtigen Logger.

Jetzt geht es mir aber um die Exceptions und da ist mir irgendwie selber noch nicht ganz klar, ob sowas, was ich mir denke überhaupt geht. Also: ich meine jetzt nicht, die gefangenen Exceptions mitzuloggen, das mache ich schon, sondern eben die Fehlerbehandlung selber zu zentralisieren, also, das was ein Progi evtl. tun soll, bei einer gefangenen Exception.

Jetzt geht es mir aber um die Exceptions und da ist mir
irgendwie selber noch nicht ganz klar, ob sowas, was ich mir
denke überhaupt geht. Also: ich meine jetzt nicht, die
gefangenen Exceptions mitzuloggen, das mache ich schon,
sondern eben die Fehlerbehandlung selber zu zentralisieren,
also, das was ein Progi evtl. tun soll, bei einer gefangenen
Exception.

Hmmm, bin mir nicht ganz sicher was du meinst.

Was nicht geht ist, ist dass du von der Sprache her einen zentralen Exception-Handler definierst an den alle geworfenen Exceptions automatisch übergeben werden, du brauchst immer noch überall deine catch-Blöcke in denen du die Exceptions fängst.

Aber dort kannst du dann die Exception von allen Stellen an eine Stelle zur Behandlung weitergeben.

So irgendwie:

try
{
 ...
}
catch( Exception e )
{
 getMyAppMainObject().getMyAppErrorHandler().handleError( e );
}

Das was Bruno gemeint hat, eine Exception-Klasse für die ganze Anwendung kann ich auch empfehlen. Also dass du z. B. Exceptions die aus einer Java-API-Komponente kommen gleich an Ort und Stelle fängst, um Zusatzinformationen erweiterst (wo ist der Fehler aufgetreten, Schwere des Fehlers etc.) und dann als eigene Exception weiterwirfst.

Das erleichtert dann auch die zentrale Fehlerbehandlung, da auf mehr Informationen zugegriffen werden kann.

Grüße, Robert

So irgendwie:

try
{

}
catch( Exception e )
{
getMyAppMainObject().getMyAppErrorHandler().handleError( e
);
}

Ja, genau so in der Art hatte ich mir das gedacht. Fragt sich nun eben nur, was die handleError-Methode am sinnigsten machen sollte.

Das was Bruno gemeint hat, eine Exception-Klasse für die ganze
Anwendung kann ich auch empfehlen. Also dass du z. B.
Exceptions die aus einer Java-API-Komponente kommen gleich an
Ort und Stelle fängst, um Zusatzinformationen erweiterst (wo
ist der Fehler aufgetreten, Schwere des Fehlers etc.) und dann
als eigene Exception weiterwirfst.

Kannst du da mal ein Beispiel aufschreiben. Nur damit es mir klarer wird. Das wäre super.

Viele Grüße

Nora

Ja, genau so in der Art hatte ich mir das gedacht. Fragt sich
nun eben nur, was die handleError-Methode am sinnigsten machen
sollte.

[…]

Kannst du da mal ein Beispiel aufschreiben. Nur damit es mir
klarer wird. Das wäre super.

Das hängt wirklich sehr stark von der Anwendung ab. Code posten hat da jetzt kaum Sinn (da wo ich grad dran arbeite hat sowohl die allgemeine Exception-Klasse als auch die allgemeine Fehlerbehandlung jeweils einige Tausend Codezeilen), ich kann dir ein paar konkrete Beispiele bringen, aber wie gesagt, sehr anwendungsspezifisch. Es handelt sich um einen sogenannten Adapter, ein Stück Software das die Schnittstelle einer Middelware zu einer Applikation darstellt.

Die allgemeine Exception-Klasse bietet u. a. folgende Funktionen:

*) Kapseln einer eventuell vorhandenen, ursprünglichen Exception. Fehlermeldung und Stacktrace der ursprünglichen Exception werden in Fehlermeldung und Stacktrace der allgemeinen Exception eingebettet.

*) Speichern von Folge-Exceptions, also Fehler die während der Fehlerbehandlung auftreten (z. B. beim Datenbank-Rollback). Auch die werden dann wiederum automatisch in die Fehlermeldung integriert.

*) Schwere/Art des Fehlers. Das wird dann von der allgemeinen Fehlerbehandlung wieder abgefragt. Fehlerklassen sind z. B.:
-) Recoverable: Fehler kann durch erneuten, späteren Versuch behoben werden, z. B. Datenbank down.
-) Non-recoverable: Fehler kann nicht durch erneuten Versuch behoben werden, z. B. Integritätsverletzung in der Datenbank
-) Start/Stop: Fehler die beim Starten/Beenden der Applikation auftreten
-) Internal: Fehler die den Erfolg einer Aktion nicht mehr beeinflussen.

Diese Klassifikation wird an Ort und Stelle an der der Fehler auftritt vorgenommen, um beim Datenbank-Beispiel zu bleiben, über den JDBC-Fehlercode oder SQL-State.

Die eigentliche Fehlerbehandlung muss mindestens zweistufig erfolgen, einmal an Ort und Stelle und einmal in der allgemeinen Fehlerbehandlung.

An Ort und Stelle wäre z. B. das schließen der aktuellen Datenbank-Verbindung, sowas kann die allgemeine Fehlerbehandlung natürlich nicht machen/wissen.

Das kann man auch mehrstufig machen. Z. b. habe ich eine allgemeine Routine um Datenbankfehler zu verarbeiten. Die schaut sich die SQLException an, klassifiziert den Fehler (also die Schwere des Fehlers), rollt Transaktionen zurück und generiert aus der SQLException und eventuellen dazugehörigen Warnings eine Fehlermeldung. Resultat ist dann eine Instanz der allgemeinen Exception-Klasse, die wird dann geworfen und von der allgemeinen Fehlerbehandlung verarbeitet.

Die allgemeine Fehlerbehandlung tut dann z. B. den Fehler einmal in Richtung Logs schreiben, das geht in ein File und an ein Systemmanagement-Tool.
Dann wird je nach Recoverable/Non-Recoverable verfahren. Im ersten Fall wird die Aktion später nochmal versucht, im zweiten Fall werden die eingehenden Daten die den Fehler ausgelöst haben wieder woanders gespeichert, die kann man dann wieder bearbeiten, eventuell den Fehler korrigieren und dann die Aktion nochmal auslösen.

Dann gibt es natürlich auch noch Spezialfälle. Z. b. ein OutOfMemoryError. Den bekommt auch die allgemeine Fehlerbehandlung, nur hat es da keinen Sinn grossartig was zu machen, da schaue ich nur, dass ich den Fehler ins Logfile bringe und die Applikation geordnet runterfahre.

Puh, das ist jetzt irgendwie ein langes Mail geworden. Ich hoffe es gibt dir ein paar Anstösse. :o)

Wenn du weitere Fragen hast, frag einfach. Oder poste mal etwas über deinen konkreten Anwendungsfall, dann finden sich sicher auch ein paar Ideen dazu. :smile:

Grüße, Robert

1 „Gefällt mir“