From 90493f4e04dc1a904d90b078db4945e8e6ed2ed9 Mon Sep 17 00:00:00 2001 From: Alejandro Revilla Date: Fri, 4 Sep 2026 11:16:15 -0300 Subject: [PATCH] fix: remove TransactionManager's static ThreadLocal context mapping The TM set two static ThreadLocals around each transaction's participant run and exposed them through the static accessors getSerializable(), getContext() and getId(). With virtual threads and a large session count that per-thread state is a leak vector, and the context already reaches every participant as a parameter. No caller exists in jPOS, jPOS-EE or the Control Plane. Closes #770 --- .../jpos/transaction/TransactionManager.java | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/jpos/src/main/java/org/jpos/transaction/TransactionManager.java b/jpos/src/main/java/org/jpos/transaction/TransactionManager.java index 813e94f474..1900d464e7 100644 --- a/jpos/src/main/java/org/jpos/transaction/TransactionManager.java +++ b/jpos/src/main/java/org/jpos/transaction/TransactionManager.java @@ -99,8 +99,6 @@ public TransactionManager() {} /** Configured group-name to participant-list mapping. */ protected Map> groups; private Set destroyables = new HashSet<>(); - private static final ThreadLocal tlContext = new ThreadLocal<>(); - private static final ThreadLocal tlId = new ThreadLocal<>(); private Metrics metrics; private Map params = new HashMap<>(); private long globalMaxTime; @@ -298,7 +296,6 @@ private void runTransaction (Serializable context, int session) { tme.begin(); try { - setThreadLocal(id, context); if (hasStatusListeners) notifyStatusListeners (session, TransactionStatusEvent.State.READY, id, "", null); @@ -347,7 +344,6 @@ private void runTransaction (Serializable context, int session) { else evt.addMessage (t); } finally { - removeThreadLocal(); if (hasStatusListeners) { notifyStatusListeners ( session, @@ -1291,31 +1287,6 @@ public int getActiveSessions() { public int getMaxSessions() { return maxSessions; } - /** - * Returns the current thread's transaction context as a raw {@link Serializable}. - * - * @return the thread-local context, or {@code null} when no transaction is in progress - */ - public static Serializable getSerializable() { - return tlContext.get(); - } - /** - * Returns the current thread's transaction context, narrowed to the caller's expected type. - * - * @param caller-supplied context type - * @return the thread-local context, or {@code null} when no transaction is in progress - */ - public static T getContext() { - return (T) tlContext.get(); - } - /** - * Returns the current thread's transaction id, when one is in progress. - * - * @return the thread-local transaction id, or {@code null} - */ - public static Long getId() { - return tlId.get(); - } private void notifyStatusListeners @@ -1334,14 +1305,6 @@ private void setThreadName (long id, String method, TransactionParticipant p) { LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault())) ); } - private void setThreadLocal (long id, Serializable context) { - tlId.set(id); - tlContext.set(context); - } - private void removeThreadLocal() { - tlId.remove(); - tlContext.remove(); - } private String getName(TransactionParticipant p) { return Optional.ofNullable(params.get(p)).map(ParticipantParams::name).orElseGet(() -> defaultParticipantName(p));