Joaquín Reñé
2026-03-27 4ee50e257b32f6ec0f72907305d1f2b1212808a4
securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
....@@ -81,18 +81,67 @@
8181 */
8282 @Override
8383 public void filter(ContainerRequestContext requestContext) throws IOException {
84
- EntityManager em = emProvider.getEntityManager();
85
- LOG.debug("GETTING EM: {}", em);
84
+
85
+ Method method = resourceInfo != null ? resourceInfo.getResourceMethod() : null;
86
+ if (method == null) {
87
+ LOG.warn("RequestsInterceptor: resource method is null");
88
+ return;
89
+ }
8690
87
- // Store EntityManager for later retrieval (writer interceptor)
88
- requestContext.setProperty(EM_CONTEXT_PROPERTY, em);
91
+ boolean securable = method.isAnnotationPresent(Securable.class);
92
+ boolean ensureTransaction = method.isAnnotationPresent(EnsureTransaction.class);
8993
90
- Method method = resourceInfo.getResourceMethod();
94
+ // Only require injected helpers when the endpoint actually needs them
95
+ if (securable) {
96
+ if (tokenHelper == null || cache == null || emProvider == null) {
97
+ LOG.error(
98
+ "RequestsInterceptor is not fully initialized for secured endpoint '{}'. " +
99
+ "tokenHelper={}, cache={}, emProvider={}",
100
+ method.getName(), tokenHelper, cache, emProvider
101
+ );
102
+ requestContext.abortWith(
103
+ Response.status(Status.INTERNAL_SERVER_ERROR)
104
+ .entity("Security infrastructure not initialized")
105
+ .build()
106
+ );
107
+ return;
108
+ }
91109
92
- if (checkSecurableMethods(requestContext, method)) {
93
- if (method.isAnnotationPresent(EnsureTransaction.class)) {
94
- LOG.debug("Beginning transaction");
95
- em.getTransaction().begin();
110
+ if (!checkSecurableMethods(requestContext, method)) {
111
+ return;
112
+ }
113
+ }
114
+
115
+ // Only open/use EM when needed
116
+ if (ensureTransaction || securable) {
117
+ EntityManager em = getEntityManagerSafely();
118
+ if (em == null) {
119
+ LOG.error("No EntityManager available for method '{}'", method.getName());
120
+ requestContext.abortWith(
121
+ Response.status(Status.INTERNAL_SERVER_ERROR)
122
+ .entity("Persistence infrastructure not initialized")
123
+ .build()
124
+ );
125
+ return;
126
+ }
127
+
128
+ LOG.debug("GETTING EM: {}", em);
129
+ requestContext.setProperty(EM_CONTEXT_PROPERTY, em);
130
+
131
+ if (ensureTransaction) {
132
+ try {
133
+ if (!em.getTransaction().isActive()) {
134
+ LOG.debug("Beginning transaction");
135
+ em.getTransaction().begin();
136
+ }
137
+ } catch (Exception e) {
138
+ LOG.error("Error beginning transaction for method '{}'", method.getName(), e);
139
+ requestContext.abortWith(
140
+ Response.status(Status.INTERNAL_SERVER_ERROR)
141
+ .entity("Could not begin transaction")
142
+ .build()
143
+ );
144
+ }
96145 }
97146 }
98147 }
....@@ -107,9 +156,11 @@
107156 * @return true if request can proceed; false when aborted
108157 */
109158 private boolean checkSecurableMethods(ContainerRequestContext ctx, Method method) {
110
- if (!method.isAnnotationPresent(Securable.class)) return true;
159
+ if (!method.isAnnotationPresent(Securable.class)) {
160
+ return true;
161
+ }
111162
112
- String token = servletRequest.getHeader(TokenHelper.TOKEN_HEADER_PÀRAM);
163
+ String token = servletRequest != null ? servletRequest.getHeader(TokenHelper.TOKEN_HEADER_PÀRAM) : null;
113164 if (token == null || !tokenHelper.isTokenValid(token)) {
114165 LOG.warn("Access denied, invalid token");
115166 ctx.abortWith(Response.status(Status.UNAUTHORIZED).build());
....@@ -126,11 +177,30 @@
126177 return false;
127178 }
128179
129
- BasicSecurityContext sc = new BasicSecurityContext(username, roles, servletRequest.isSecure());
180
+ boolean secure = servletRequest != null && servletRequest.isSecure();
181
+ BasicSecurityContext sc = new BasicSecurityContext(username, roles, secure);
130182 sc.setOrganizationsIds(getUserOrganizations(username));
131183 sc.setApplicationsIds(getUserApplications(username));
132184 ctx.setSecurityContext(sc);
133185 return true;
186
+ }
187
+
188
+ /**
189
+ * getEntityManagerSafely<p>
190
+ * Get the entity manager in a safely way
191
+ *
192
+ * @return entityManager
193
+ */
194
+ private EntityManager getEntityManagerSafely() {
195
+ try {
196
+ if (emProvider == null) {
197
+ return null;
198
+ }
199
+ return emProvider.getEntityManager();
200
+ } catch (Exception e) {
201
+ LOG.error("Error obtaining EntityManager from provider", e);
202
+ return null;
203
+ }
134204 }
135205
136206 // -------------------------------------------------------------
....@@ -145,18 +215,31 @@
145215 * @return userRoles
146216 */
147217 private int getUserRoles(String username) {
148
- if (username == null) return 0;
149
- Integer cached = cache.get("roles_" + username, Integer.class);
150
- if (cached != null) return cached;
218
+ if (username == null || cache == null) {
219
+ return 0;
220
+ }
151221
152
- EntityManager em = emProvider.getEntityManager();
222
+ Integer cached = cache.get("roles_" + username, Integer.class);
223
+ if (cached != null) {
224
+ return cached;
225
+ }
226
+
227
+ EntityManager em = getEntityManagerSafely();
228
+ if (em == null) {
229
+ LOG.error("Cannot resolve user roles: EntityManager is not available");
230
+ return 0;
231
+ }
232
+
153233 User user = em.find(User.class, username);
154234 int roles = 0;
155235 if (user != null) {
156236 List<Integer> r = user.getRoles();
157
- if (r != null) for (Integer role : r) roles += role;
237
+ if (r != null) {
238
+ for (Integer role : r) {
239
+ roles += role;
240
+ }
241
+ }
158242 cache.set("roles_" + username, roles, 3600);
159
- // also warm some caches
160243 cache.set("orgs_" + username, user.getOrgsIds(), 3600);
161244 }
162245 return roles;
....@@ -171,10 +254,22 @@
171254 * @return userOrganizations
172255 */
173256 private Set<Integer> getUserOrganizations(String username) {
174
- Set<Integer> cached = cache.getSet("orgs_" + username, Integer.class);
175
- if (cached != null) return cached;
257
+ if (username == null || cache == null) {
258
+ return Set.of();
259
+ }
176260
177
- User user = emProvider.getEntityManager().find(User.class, username);
261
+ Set<Integer> cached = cache.getSet("orgs_" + username, Integer.class);
262
+ if (cached != null) {
263
+ return cached;
264
+ }
265
+
266
+ EntityManager em = getEntityManagerSafely();
267
+ if (em == null) {
268
+ LOG.error("Cannot resolve user organizations: EntityManager is not available");
269
+ return Set.of();
270
+ }
271
+
272
+ User user = em.find(User.class, username);
178273 if (user != null) {
179274 Set<Integer> result = user.getAllOrgsIds();
180275 cache.set("orgs_" + username, result, 3600);
....@@ -192,10 +287,22 @@
192287 * @return userApplications
193288 */
194289 private Set<Integer> getUserApplications(String username) {
195
- Set<Integer> cached = cache.getSet("apps_" + username, Integer.class);
196
- if (cached != null) return cached;
290
+ if (username == null || cache == null) {
291
+ return Set.of();
292
+ }
197293
198
- User user = emProvider.getEntityManager().find(User.class, username);
294
+ Set<Integer> cached = cache.getSet("apps_" + username, Integer.class);
295
+ if (cached != null) {
296
+ return cached;
297
+ }
298
+
299
+ EntityManager em = getEntityManagerSafely();
300
+ if (em == null) {
301
+ LOG.error("Cannot resolve user applications: EntityManager is not available");
302
+ return Set.of();
303
+ }
304
+
305
+ User user = em.find(User.class, username);
199306 if (user != null) {
200307 Set<Integer> result = user.getAllAppsIds();
201308 cache.set("apps_" + username, result, 3600);
....@@ -218,30 +325,45 @@
218325 */
219326 @Override
220327 public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
221
- context.proceed();
222
-
223
- EntityManager em = (EntityManager) context.getProperty(EM_CONTEXT_PROPERTY);
224
- if (em == null) return;
225
-
226328 try {
227
- if (em.getTransaction().isActive()) {
228
- if (servletResponse.getStatus() == Status.OK.getStatusCode()) {
229
- em.getTransaction().commit();
230
- LOG.debug("Transaction committed");
231
- } else {
232
- em.getTransaction().rollback();
233
- LOG.debug("Transaction rolled back");
234
- }
235
- }
329
+ context.proceed();
236330 } finally {
237
- if (em.isOpen()) {
331
+ EntityManager em = (EntityManager) context.getProperty(EM_CONTEXT_PROPERTY);
332
+ if (em == null) {
333
+ return;
334
+ }
335
+
336
+ try {
337
+ if (em.getTransaction() != null && em.getTransaction().isActive()) {
338
+ int status = servletResponse != null ? servletResponse.getStatus() : Status.INTERNAL_SERVER_ERROR.getStatusCode();
339
+ if (status >= 200 && status < 300) {
340
+ em.getTransaction().commit();
341
+ LOG.debug("Transaction committed");
342
+ } else {
343
+ em.getTransaction().rollback();
344
+ LOG.debug("Transaction rolled back");
345
+ }
346
+ }
347
+ } catch (Exception e) {
348
+ LOG.error("Error finalizing transaction", e);
238349 try {
239
- em.close();
350
+ if (em.getTransaction() != null && em.getTransaction().isActive()) {
351
+ em.getTransaction().rollback();
352
+ }
353
+ } catch (Exception rollbackEx) {
354
+ LOG.error("Error rolling back transaction", rollbackEx);
355
+ }
356
+ } finally {
357
+ try {
358
+ if (em.isOpen()) {
359
+ em.close();
360
+ }
240361 } catch (Exception e) {
241362 LOG.error("Error closing EntityManager", e);
242363 }
243364 }
244365 }
245366 }
367
+
246368 }
247369