Joaquín Reñé
2025-10-07 146a0fb8b0e90f9196e569152f649baf60d6cc8f
securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java
....@@ -1,3 +1,6 @@
1
+/*
2
+ * Copyright @ 2013 CurisTEC, S.A.S. All Rights Reserved.
3
+ */
14 package net.curisit.securis;
25
36 import jakarta.persistence.EntityManager;
....@@ -17,18 +20,49 @@
1720 import net.curisit.securis.services.exception.SeCurisServiceException;
1821 import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
1922
23
+/**
24
+* DefaultExceptionHandler
25
+* <p>
26
+* JAX-RS {@link ExceptionMapper} that normalizes error responses across the API.
27
+* It also makes a best-effort to rollback and close a request-scoped {@link EntityManager}
28
+* if still open.
29
+*
30
+* <p>Response strategy:
31
+* <ul>
32
+* <li>{@link ForbiddenException} → 401 UNAUTHORIZED with app-specific error headers.</li>
33
+* <li>{@link SeCurisServiceException} → 418 (custom) with app error headers.</li>
34
+* <li>Other exceptions → 500 with generic message and request context logging.</li>
35
+* </ul>
36
+*
37
+* Headers:
38
+* <ul>
39
+* <li>{@code X-SECURIS-ERROR-MSG}</li>
40
+* <li>{@code X-SECURIS-ERROR-CODE}</li>
41
+* </ul>
42
+*
43
+* @author JRA
44
+* Last reviewed by JRA on Oct 6, 2025.
45
+*/
2046 @Provider
2147 public class DefaultExceptionHandler implements ExceptionMapper<Exception> {
48
+
2249 private static final Logger LOG = LogManager.getLogger(DefaultExceptionHandler.class);
23
-
50
+
51
+ /** Default status code used for application-defined errors. */
2452 public static final int DEFAULT_APP_ERROR_STATUS_CODE = 418;
53
+
54
+ /** Header name carrying a human-readable error message. */
2555 public static final String ERROR_MESSAGE_HEADER = "X-SECURIS-ERROR-MSG";
56
+
57
+ /** Header name carrying a symbolic application error code. */
2658 public static final String ERROR_CODE_MESSAGE_HEADER = "X-SECURIS-ERROR-CODE";
2759
60
+ /** Default constructor (logs instantiation). */
2861 public DefaultExceptionHandler() {
2962 LOG.info("Creating DefaultExceptionHandler ");
3063 }
3164
65
+ // Context objects injected by the runtime
3266 @Context
3367 HttpServletRequest request;
3468 @Context
....@@ -36,6 +70,12 @@
3670 @Context
3771 EntityManager em;
3872
73
+ /**
74
+ * toResponse
75
+ * <p>
76
+ * Map a thrown exception to an HTTP {@link Response}, releasing the {@link EntityManager}
77
+ * if present.
78
+ */
3979 @Override
4080 public Response toResponse(Exception e) {
4181 releaseEntityManager();
....@@ -57,6 +97,11 @@
5797 return Response.serverError().header(ERROR_MESSAGE_HEADER, "Unexpected error: " + e.toString()).type(MediaType.APPLICATION_JSON).build();
5898 }
5999
100
+ /**
101
+ * releaseEntityManager
102
+ * <p>
103
+ * Best-effort cleanup: rollback active transaction (if joined) and close the {@link EntityManager}.
104
+ */
60105 private void releaseEntityManager() {
61106 try {
62107 if (em != null && em.isOpen()) {