Skip to content

Commit fbc8d58

Browse files
milanmajchrakclaude
authored andcommitted
fix: abort leaked request Context in StatelessAuthenticationFilter (backport dc57ffd / #852)
Backport the behavioral fix from dc57ffd ("Transaction bug - close context in finally block", PR #852) which is on dtq-dev/customer/lindat but missing from customer/zcu-data. On the request error path a slow submission upload could leave its Hibernate session bound to the Tomcat thread with a dirty, stale Item: the upload throws before reaching context.commit(), and DSpaceRequestContextFilter assigns its `context` local only AFTER chain.doFilter, so on an exception the local stays null and its finally skips the abort -> the session leaks. A later request on that thread then flushes the stale Item as a full-row UPDATE (Item has no @DynamicUpdate/@Version), reverting owning_collection->NULL and in_archive->false while collection2item + handle survive -> the item becomes an unsearchable orphan (e.g. handle 20.500.14592/107). Wrap chain.doFilter in the outer StatelessAuthenticationFilter with a try/finally that reads the Context from the request attribute and abort()s it if still valid, cleaning up the leaked context the inner filter missed. No-op on the normal success path. Only the StatelessAuthenticationFilter hunk is ported; the diagnostic/CI files in dc57ffd are omitted (they conflict and are not needed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit ea6116e)
1 parent 84e930c commit fbc8d58

1 file changed

Lines changed: 17 additions & 1 deletion

File tree

dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatelessAuthenticationFilter.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,23 @@ protected void doFilterInternal(HttpServletRequest req,
102102
if (authentication != null) {
103103
SecurityContextHolder.getContext().setAuthentication(authentication);
104104
}
105-
chain.doFilter(req, res);
105+
106+
try {
107+
chain.doFilter(req, res);
108+
} finally {
109+
// Complete the context to avoid transactions getting stuck in the connection pool in the
110+
// `idle in transaction` state.
111+
// TODO add the issue url
112+
Context context = (Context) req.getAttribute(ContextUtil.DSPACE_CONTEXT);
113+
// Ensure the context is cleared after the request is done
114+
if (context != null && context.isValid()) {
115+
try {
116+
context.abort();
117+
} catch (Exception e) {
118+
log.error("{} occurred while trying to close", e.getMessage(), e);
119+
}
120+
}
121+
}
106122
}
107123

108124
/**

0 commit comments

Comments
 (0)