#800: ExceptionHelper.java
projectforge-business/src/main/java/org/projectforge/framework/utils/ExceptionHelper.java · 97 líneas · 50 código · 39 comentarios · 8 en blanco
Tres métodos de utilidad estáticos para el manejo de excepciones: trazas de pila filtradas (colapsa marcos irrelevantes y omite proxies CGLIB), traza de pila a String (printStackTrace estándar a escritor), y resolución recursiva de causa raíz. Se utiliza principalmente en la capa de seguridad/acceso para producir mensajes de error legibles que muestren solo las rutas de código de ProjectForge, no los internos de Spring/Hibernate/Tomcat.
Métodos
| Método | Qué hace | Por qué existe |
getFilteredStackTrace(ex, namespace) |
Construye una cadena de traza de pila que contiene solo marcos del espacio de nombres dado. Los marcos consecutivos que no coinciden se colapsan en "at ...". Los marcos que contienen CGLIB$$ siempre se omiten — son clases proxy de Hibernate con nombres distorsionados como AddressDO$$EnhancerByCGLIB$$a1b2c3d4. |
Los errores de violación de acceso mostrarían de otro modo 50+ líneas de internos de Spring Security y Tomcat antes de mostrar la única línea relevante de ProjectForge. La traza filtrada muestra solo la cadena de llamadas relevante para el desarrollador. |
printStackTrace(ex) |
Convierte una traza de pila completa a String mediante StringWriter+PrintWriter. Patrón estándar de Java. |
Los frameworks de registro necesitan String, no PrintStream. Se usa cuando las excepciones deben serializarse a JSON o almacenarse en columnas de base de datos. |
getRootCause(ex) |
Desenvuelve recursivamente getCause() hasta encontrar la excepción más interna. Devuelve la excepción original si no existe causa. |
Spring envuelve excepciones en gran medida (UndeclaredThrowableException, InvocationTargetException, DataAccessException). El error real siempre está al fondo. Este método lo extrae. |
Algoritmo de filtrado por espacio de nombres
El método getFilteredStackTrace utiliza un enfoque de máquina de estados con dos modos:
Modo normal: Imprime marcos. Cuando se encuentra un marco que no coincide, genera "at ..." (colapsando los marcos irrelevantes) y cambia a modo ignorado.
Modo ignorado: Omite marcos silenciosamente hasta que aparece un marco coincidente, luego vuelve al modo normal y lo imprime.
Esto produce una salida compacta como: at org.projectforge.access.AccessChecker.check(AccessChecker.java:79) at ... at org.projectforge.task.TaskDao.hasAccess(TaskDao.java:176) — donde "at ..." reemplaza todos los marcos de Spring/Tomcat/Hibernate entre las dos líneas relevantes.
Consumidores
Es llamado por la capa de control de acceso (AccessCheckerImpl, AccessException) al construir mensajes de error para violaciones de permisos. También es usado por ScriptExecutor para producir salida de error legible en fallos de scripts Groovy/Kotlin — sin la traza filtrada, un simple NPE en un script produciría una traza de pila de 200 líneas dominada por el runtime de Groovy y los internos de los proxies de Spring.
Historial Git
| Commit | Qué cambió |
868d6abb7 | Copyright 2025→2026 |
63081666f | Copyright 2024→2025 |
b6092df09 | Copyright 2023→2024 |
ab45d51fa | Copyright 2001-2022→2001-2023 |
5f7ef41b8 | Copyright 2021→2022 |
ceb63e8a1 | Copyright 2001-2021 |
7c79f192 | Copyright 2020 |
73a9755d | Pase de limpieza de código en todas las utilidades. Se colapsaron bloques catch idénticos, se reemplazó ArrayList<Class> con el operador diamante ArrayList<>, se reemplazó StringBuffer con StringBuilder, se cambió Collections.sort a List.sort. El propio código de ExceptionHelper usa StringBuilder en getFilteredStackTrace — este commit aseguró consistencia con la migración global del proyecto de StringBuffer sincronizado a StringBuilder no sincronizado. |
Advertencia — Detección de CGLIB$$: El método ignore() verifica CGLIB$$ en el nombre de la clase. Cuando ProjectForge actualice a Hibernate 6.x, los proxies usarán ByteBuddy en lugar de CGLIB — los nombres de clase contendrán $HibernateProxy$ o $ByteBuddy$ en su lugar. El método ignore() necesitará actualizarse para manejar ambos patrones.