fix: handle already-active CDI request context in deferred destruction#950
Conversation
When a Quarkus request filter has already activated the CDI request context before runWithDeferredContextDestruction() is called, the method previously skipped the deferred-destruction logic and ran the task directly. This allowed the request filter to call terminate() and destroy @RequestScoped beans while the ManagedExecutor agent thread was still running, causing failures when accessing OIDC token credentials. Now the method always takes ownership of the context lifecycle: it captures the existing state (or activates a fresh context), deactivates in the finally block so Arc's terminate() becomes a no-op, and defers actual destruction to the SSE response endHandler/closeHandler. This fixes a2aproject#949 Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
There was a problem hiding this comment.
Code Review
This pull request updates VertxSecurityHelper to improve CDI request context lifecycle management during deferred (streaming/SSE) requests. Specifically, if a CDI context is already active, it now captures the existing state and takes ownership of its deferred destruction instead of bypassing the cleanup registration. A comprehensive unit test suite VertxSecurityHelperTest has been added to verify these behaviors under various scenarios. Additionally, minor whitespace cleanup was performed in DefaultRequestHandler. There are no review comments, so I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
When a Quarkus request filter has already activated the CDI request context before runWithDeferredContextDestruction() is called, the method previously skipped the deferred-destruction logic and ran the task directly. This allowed the request filter to call terminate() and destroy @RequestScoped beans while the ManagedExecutor agent thread was still running, causing failures when accessing OIDC token credentials.
Now the method always takes ownership of the context lifecycle: it captures the existing state (or activates a fresh context), deactivates in the finally block so Arc's terminate() becomes a no-op, and defers actual destruction to the SSE response endHandler/closeHandler.
Fixes #949 🦕