Ich komme wieder nicht wirklich weiter.
Folgendes: Wenn meine Applikation, die für das Servlet nur ein einziges Objekt darstellt, instantiiert wird, startet sie intern einen Prozess, der über einen ScheduldedExecutorService ausgeführt wird.
Das geht so:
ScheduldedProcess p = new ScheduldedProcess(params);
p.startLookUp() -> startet einen Schedulded Thread. Der wird z.B. alle 30 Sekunden durchgeführt und schreibt in eine Queue, ob es etwas zu machen gibt und wenn ja, was.
p.startAsyncProcessing() -> startet alle 30 Sekunden ebenfalls einen Thread. Die Klasse heißt z.B. AsyncExecutor.
Innerhalb von AsyncExecutor wird die Queue über eine While-Schleife ausgelesen. Für jeden Eintrag wird ein Thread von einem normalen ExecutorService gestartet. Dieser verarbeitet immer genau einen Queue-Eintrag.
Für das ExceptionHandling habe ich mir jetzt folgendes ausgedacht: Jeder asynchrone Prozess erstellt ein StatusMessage-Objekt, in dem unter anderem auch die geworfenen Exceptions (die StackTraces) gespeichert werden. Dieses StatusMessage-Objekt schreibe ich in die Datenbank.
Das Problem ist, wenn die Exception bei der Datenbank auftreten würde, würde ich über die StatusMessage nie davon erfahren. Ich könnte sie jetzt noch auf Platte schreiben - das klingt designtechnisch aber nach ner schlechten Idee, weil StatusMessage dann Zugang zu einem zweiten DAO bräuchte.
Da das ApplicationObject, welches p instantiiert und ausführt, p eigentlich nicht mehr aufruft, weiß ich nicht, wie ich über p entstandene Exceptions abfangen soll.
Was ich mir vorstellen könnte wäre ein Hack. Ich glaube, dass UncaughtExceptionHandler (UEH) in diesem Falle Abhilfe schaffen könnte, oder? Wenn ich den UEH im AsyncExecutor unterbringe und er aber außerhalb von p referenziert wird, kann ich auf UEHs Exceptions zurückgreifen.
Jetzt stellt sich nur noch die Frage, wer holt die dort geworfenen Exceptions ab?
Ich könnte jedesmal wenn myApp.getAnswer() aufgerufen wird, checken, ob der UEH Exceptions enthält und diese dann ignorieren - haben mit .getAnswer() ja nichts zu tun -, aber in ein .log-File schreiben. Ich empfinde es aber als schlechten Stil, wenn .getAnswer, nur weil es die am stärksten frequentierte Methode wäre, das ExceptionHandling für Prozesse übernimmt, die nichts mit .getAnswer() zu tun haben.
Ich könnte mir nur vorstellen, noch einen Schedulded-Thread bei der Instantiierung von myApp zu starten. Der schaut z.B. alle 60 Sekunden nach, ob's ne Exception gibt, die aufgrund eines SQL-Fehlers (oder eines anderen DAO-Fehlers) nicht über die üblichen Kanäle behandelt werden konnte. Diese Exception holt er aus dem UEH und schreibt sie auf Platte.
Es könnte jetzt nur noch eine IOException in die Quere kommen. Wenn die Datei, die geschrieben wird, aber einen eindeutigen Namen erhält, dann ist die einzige Möglichkeit für einen IO-Fehler eigentlich nur noch defekte Hardware. Und wenn das der Fall ist, meckert Tomcat (bei einem Servlet) oder der Rechner, bei einer Desktopanwendung, bereits von selbst.
Denke ich hier zu kompliziert?
Danke für jede Anregung!
EDIT: Lösungsansatz: Logger
Ich habe bei weiteren Recherchen in den letzten Stunden was interessantes entdeckt: Den Java Logger.
Statt das Ganze so komplex aufzusetzen, wie ich es eben beschrieb, kann man es ja auch mit einem Logger lösen.
Alle run() Methoden werden grundsätzlich von einem Try-Catch-Block umschlossen, wenn future.get() vermieden werden soll. Im Catch-Block wende ich dann einen Logger an, der die geworfenen Exceptions via logger.throwing() mitloggt.
Falls die Exception auch außerhalb des Threads abgefangen werden kann, weil man future.get() verwenden will, könnte man auf logger.throwing() verzichten und stattdessen dort via logger.log() die uncatched Exception abfangen.
Falls der Ansatz hier ein positives Feedback erfährt, bereite ich dafür vielleicht auch mal ein komplexeres Tutorial vor.