EN · DE · RU · FR · ES

#800: ExceptionHelper.java

projectforge-business/src/main/java/org/projectforge/framework/utils/ExceptionHelper.java · 97 Zeilen · 50 Code · 39 Kommentare · 8 Leerzeilen
Drei statische Hilfsmethoden für die Ausnahmebehandlung: Gefilterte Stacktraces (irrelevante Frames zusammenfalten und CGLIB-Proxys überspringen), Stacktrace in String (Standard-printStackTrace-in-Writer) und rekursive Ursachenermittlung. Hauptsächlich von der Sicherheits-/Zugriffsschicht verwendet, um lesbare Fehlermeldungen zu erzeugen, die nur ProjectForge-Codepfade zeigen, nicht Spring/Hibernate/Tomcat-Interna.

Methoden

MethodeFunktionExistenzgrund
getFilteredStackTrace(ex, namespace)Erstellt einen Stacktrace-String, der nur Frames aus dem angegebenen Namensraum enthält. Aufeinanderfolgende nicht passende Frames werden zu "at ..." zusammengefasst. Frames mit CGLIB$$ werden immer übersprungen – dies sind Hibernate-Proxy-Klassen mit verstümmelten Namen wie AddressDO$$EnhancerByCGLIB$$a1b2c3d4.Zugriffsverletzungsfehler würden sonst 50+ Zeilen Spring Security- und Tomcat-Interna anzeigen, bevor die einzelne relevante ProjectForge-Zeile erscheint. Der gefilterte Trace zeigt nur die für den Entwickler relevante Aufrufkette.
printStackTrace(ex)Wandelt einen vollständigen Stacktrace über StringWriter+PrintWriter in einen String um. Standard-Java-Muster.Logging-Frameworks benötigen String, nicht PrintStream. Wird verwendet, wenn Ausnahmen in JSON serialisiert oder in Datenbankspalten gespeichert werden müssen.
getRootCause(ex)Entpackt rekursiv getCause(), bis die innerste Ausnahme gefunden wird. Gibt die ursprüngliche Ausnahme zurück, wenn keine Ursache existiert.Spring umschließt Ausnahmen stark (UndeclaredThrowableException, InvocationTargetException, DataAccessException). Der eigentliche Fehler liegt immer ganz unten. Diese Methode extrahiert ihn.

Namensraum-Filteralgorithmus

Die Methode getFilteredStackTrace verwendet einen Zustandsautomaten-Ansatz mit zwei Modi:

Normalmodus: Frames ausgeben. Wenn ein nicht passender Frame auftritt, wird "at ..." ausgegeben (die irrelevanten Frames werden zusammengefasst) und in den Ignoriermodus gewechselt.
Ignoriermodus: Frames stillschweigend überspringen, bis ein passender Frame erscheint, dann zurück in den Normalmodus wechseln und diesen ausgeben.

Dies erzeugt kompakte Ausgaben wie: at org.projectforge.access.AccessChecker.check(AccessChecker.java:79) at ... at org.projectforge.task.TaskDao.hasAccess(TaskDao.java:176) – wobei "at ..." alle Spring/Tomcat/Hibernate-Frames zwischen den beiden relevanten Zeilen ersetzt.

Verwender

Wird von der Zugriffskontrollschicht (AccessCheckerImpl, AccessException) beim Erstellen von Fehlermeldungen für Berechtigungsverletzungen aufgerufen. Wird auch von ScriptExecutor verwendet, um lesbare Fehlerausgaben für fehlgeschlagene Groovy/Kotlin-Skripte zu erzeugen – ohne den gefilterten Trace würde eine einfache NPE in einem Skript einen 200-zeiligen Stacktrace erzeugen, der von Groovy-Laufzeit- und Spring-Proxy-Interna dominiert wird.

Git-Verlauf

CommitÄnderungen
868d6abb7Copyright 2025→2026
63081666fCopyright 2024→2025
b6092df09Copyright 2023→2024
ab45d51faCopyright 2001-2022→2001-2023
5f7ef41b8Copyright 2021→2022
ceb63e8a1Copyright 2001-2021
7c79f192Copyright 2020
73a9755dCode-Bereinigung für alle Utils. Identische Catch-Blöcke zusammengefasst, ArrayList<Class> durch Diamant-Operator ArrayList<> ersetzt, StringBuffer durch StringBuilder ersetzt, Collections.sort durch List.sort ersetzt. Der ExceptionHelper-Code selbst verwendet StringBuilder in getFilteredStackTrace – dieser Commit stellte die Konsistenz mit der projektsweiten Migration von synchronisiertem StringBuffer zu unsynchronisiertem StringBuilder sicher.
Achtung – CGLIB$$-Erkennung: Die Methode ignore() prüft auf CGLIB$$ im Klassennamen. Wenn ProjectForge auf Hibernate 6.x aktualisiert, werden Proxys ByteBuddy anstelle von CGLIB verwenden – die Klassennamen enthalten dann $HibernateProxy$ oder $ByteBuddy$. Die Methode ignore() muss aktualisiert werden, um beide Muster zu verarbeiten.