From 4ee50e257b32f6ec0f72907305d1f2b1212808a4 Mon Sep 17 00:00:00 2001
From: Joaquín Reñé <jrene@curisit.net>
Date: Fri, 27 Mar 2026 15:07:12 +0000
Subject: [PATCH] #4479 - upgrade SecurisServer to Java 21
---
securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java | 202 ++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 162 insertions(+), 40 deletions(-)
diff --git a/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java b/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
index 2417954..dcc89b9 100644
--- a/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
+++ b/securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
@@ -81,18 +81,67 @@
*/
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
- EntityManager em = emProvider.getEntityManager();
- LOG.debug("GETTING EM: {}", em);
+
+ Method method = resourceInfo != null ? resourceInfo.getResourceMethod() : null;
+ if (method == null) {
+ LOG.warn("RequestsInterceptor: resource method is null");
+ return;
+ }
- // Store EntityManager for later retrieval (writer interceptor)
- requestContext.setProperty(EM_CONTEXT_PROPERTY, em);
+ boolean securable = method.isAnnotationPresent(Securable.class);
+ boolean ensureTransaction = method.isAnnotationPresent(EnsureTransaction.class);
- Method method = resourceInfo.getResourceMethod();
+ // Only require injected helpers when the endpoint actually needs them
+ if (securable) {
+ if (tokenHelper == null || cache == null || emProvider == null) {
+ LOG.error(
+ "RequestsInterceptor is not fully initialized for secured endpoint '{}'. " +
+ "tokenHelper={}, cache={}, emProvider={}",
+ method.getName(), tokenHelper, cache, emProvider
+ );
+ requestContext.abortWith(
+ Response.status(Status.INTERNAL_SERVER_ERROR)
+ .entity("Security infrastructure not initialized")
+ .build()
+ );
+ return;
+ }
- if (checkSecurableMethods(requestContext, method)) {
- if (method.isAnnotationPresent(EnsureTransaction.class)) {
- LOG.debug("Beginning transaction");
- em.getTransaction().begin();
+ if (!checkSecurableMethods(requestContext, method)) {
+ return;
+ }
+ }
+
+ // Only open/use EM when needed
+ if (ensureTransaction || securable) {
+ EntityManager em = getEntityManagerSafely();
+ if (em == null) {
+ LOG.error("No EntityManager available for method '{}'", method.getName());
+ requestContext.abortWith(
+ Response.status(Status.INTERNAL_SERVER_ERROR)
+ .entity("Persistence infrastructure not initialized")
+ .build()
+ );
+ return;
+ }
+
+ LOG.debug("GETTING EM: {}", em);
+ requestContext.setProperty(EM_CONTEXT_PROPERTY, em);
+
+ if (ensureTransaction) {
+ try {
+ if (!em.getTransaction().isActive()) {
+ LOG.debug("Beginning transaction");
+ em.getTransaction().begin();
+ }
+ } catch (Exception e) {
+ LOG.error("Error beginning transaction for method '{}'", method.getName(), e);
+ requestContext.abortWith(
+ Response.status(Status.INTERNAL_SERVER_ERROR)
+ .entity("Could not begin transaction")
+ .build()
+ );
+ }
}
}
}
@@ -107,9 +156,11 @@
* @return true if request can proceed; false when aborted
*/
private boolean checkSecurableMethods(ContainerRequestContext ctx, Method method) {
- if (!method.isAnnotationPresent(Securable.class)) return true;
+ if (!method.isAnnotationPresent(Securable.class)) {
+ return true;
+ }
- String token = servletRequest.getHeader(TokenHelper.TOKEN_HEADER_PÀRAM);
+ String token = servletRequest != null ? servletRequest.getHeader(TokenHelper.TOKEN_HEADER_PÀRAM) : null;
if (token == null || !tokenHelper.isTokenValid(token)) {
LOG.warn("Access denied, invalid token");
ctx.abortWith(Response.status(Status.UNAUTHORIZED).build());
@@ -126,11 +177,30 @@
return false;
}
- BasicSecurityContext sc = new BasicSecurityContext(username, roles, servletRequest.isSecure());
+ boolean secure = servletRequest != null && servletRequest.isSecure();
+ BasicSecurityContext sc = new BasicSecurityContext(username, roles, secure);
sc.setOrganizationsIds(getUserOrganizations(username));
sc.setApplicationsIds(getUserApplications(username));
ctx.setSecurityContext(sc);
return true;
+ }
+
+ /**
+ * getEntityManagerSafely<p>
+ * Get the entity manager in a safely way
+ *
+ * @return entityManager
+ */
+ private EntityManager getEntityManagerSafely() {
+ try {
+ if (emProvider == null) {
+ return null;
+ }
+ return emProvider.getEntityManager();
+ } catch (Exception e) {
+ LOG.error("Error obtaining EntityManager from provider", e);
+ return null;
+ }
}
// -------------------------------------------------------------
@@ -145,18 +215,31 @@
* @return userRoles
*/
private int getUserRoles(String username) {
- if (username == null) return 0;
- Integer cached = cache.get("roles_" + username, Integer.class);
- if (cached != null) return cached;
+ if (username == null || cache == null) {
+ return 0;
+ }
- EntityManager em = emProvider.getEntityManager();
+ Integer cached = cache.get("roles_" + username, Integer.class);
+ if (cached != null) {
+ return cached;
+ }
+
+ EntityManager em = getEntityManagerSafely();
+ if (em == null) {
+ LOG.error("Cannot resolve user roles: EntityManager is not available");
+ return 0;
+ }
+
User user = em.find(User.class, username);
int roles = 0;
if (user != null) {
List<Integer> r = user.getRoles();
- if (r != null) for (Integer role : r) roles += role;
+ if (r != null) {
+ for (Integer role : r) {
+ roles += role;
+ }
+ }
cache.set("roles_" + username, roles, 3600);
- // also warm some caches
cache.set("orgs_" + username, user.getOrgsIds(), 3600);
}
return roles;
@@ -171,10 +254,22 @@
* @return userOrganizations
*/
private Set<Integer> getUserOrganizations(String username) {
- Set<Integer> cached = cache.getSet("orgs_" + username, Integer.class);
- if (cached != null) return cached;
+ if (username == null || cache == null) {
+ return Set.of();
+ }
- User user = emProvider.getEntityManager().find(User.class, username);
+ Set<Integer> cached = cache.getSet("orgs_" + username, Integer.class);
+ if (cached != null) {
+ return cached;
+ }
+
+ EntityManager em = getEntityManagerSafely();
+ if (em == null) {
+ LOG.error("Cannot resolve user organizations: EntityManager is not available");
+ return Set.of();
+ }
+
+ User user = em.find(User.class, username);
if (user != null) {
Set<Integer> result = user.getAllOrgsIds();
cache.set("orgs_" + username, result, 3600);
@@ -192,10 +287,22 @@
* @return userApplications
*/
private Set<Integer> getUserApplications(String username) {
- Set<Integer> cached = cache.getSet("apps_" + username, Integer.class);
- if (cached != null) return cached;
+ if (username == null || cache == null) {
+ return Set.of();
+ }
- User user = emProvider.getEntityManager().find(User.class, username);
+ Set<Integer> cached = cache.getSet("apps_" + username, Integer.class);
+ if (cached != null) {
+ return cached;
+ }
+
+ EntityManager em = getEntityManagerSafely();
+ if (em == null) {
+ LOG.error("Cannot resolve user applications: EntityManager is not available");
+ return Set.of();
+ }
+
+ User user = em.find(User.class, username);
if (user != null) {
Set<Integer> result = user.getAllAppsIds();
cache.set("apps_" + username, result, 3600);
@@ -218,30 +325,45 @@
*/
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
- context.proceed();
-
- EntityManager em = (EntityManager) context.getProperty(EM_CONTEXT_PROPERTY);
- if (em == null) return;
-
try {
- if (em.getTransaction().isActive()) {
- if (servletResponse.getStatus() == Status.OK.getStatusCode()) {
- em.getTransaction().commit();
- LOG.debug("Transaction committed");
- } else {
- em.getTransaction().rollback();
- LOG.debug("Transaction rolled back");
- }
- }
+ context.proceed();
} finally {
- if (em.isOpen()) {
+ EntityManager em = (EntityManager) context.getProperty(EM_CONTEXT_PROPERTY);
+ if (em == null) {
+ return;
+ }
+
+ try {
+ if (em.getTransaction() != null && em.getTransaction().isActive()) {
+ int status = servletResponse != null ? servletResponse.getStatus() : Status.INTERNAL_SERVER_ERROR.getStatusCode();
+ if (status >= 200 && status < 300) {
+ em.getTransaction().commit();
+ LOG.debug("Transaction committed");
+ } else {
+ em.getTransaction().rollback();
+ LOG.debug("Transaction rolled back");
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Error finalizing transaction", e);
try {
- em.close();
+ if (em.getTransaction() != null && em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ } catch (Exception rollbackEx) {
+ LOG.error("Error rolling back transaction", rollbackEx);
+ }
+ } finally {
+ try {
+ if (em.isOpen()) {
+ em.close();
+ }
} catch (Exception e) {
LOG.error("Error closing EntityManager", e);
}
}
}
}
+
}
--
Gitblit v1.3.2