Skip to content

Use a new ELContext for every call of the CdiResolver - #4305

Open
adityaanikam wants to merge 2 commits into
flowable:mainfrom
adityaanikam:fix/cdi-resolver-el-context-4302
Open

adityaanikam wants to merge 2 commits into
flowable:mainfrom
adityaanikam:fix/cdi-resolver-el-context-4302

Conversation

@adityaanikam

Copy link
Copy Markdown

CdiResolver created one jakarta.el.ELContext in its constructor and passed it to the resolver of the CDI container on every call. A jakarta.el.ELContext must not be shared between threads, and Weld keeps a stack of creational contexts in it: its lookup of a @Dependent bean checks if the stack is empty, pushes, peeks and pops. When asynchronous jobs on several threads evaluate expressions through the same CdiResolver, one thread can pop the entry while another one still peeks, which fails with an EmptyStackException.

The context is now created for every call with createELContext(), so calls that run at the same time no longer share it. A call on one thread behaves as before, because the stack is empty at the start of every lookup. The createELContext() method replaces the protected context field and the constructor of CdiResolver.

CdiResolverTest lets two threads call the resolver at the same time and checks that they get different contexts. I did not reproduce the EmptyStackException itself with Weld, the test covers the shared context that causes it.

Fixes #4302

Check List:

  • Unit tests: YES
  • Documentation: NA

CdiResolver created one jakarta.el.ELContext in its constructor and
passed it to the resolver of the CDI container on every call. Weld keeps
its stack of creational contexts in that context and its lookup of a
@dependent bean checks if the stack is empty, pushes, peeks and pops.
When jobs on several threads use the same CdiResolver, one thread can
pop while another one still peeks, which fails with an
EmptyStackException.

Create the context per call with createELContext(), which replaces the
protected context field.
Copilot AI balanced review requested due to automatic review settings October 11, 2026 11:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@filiphr filiphr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @adityaanikam. Shouldn't we maybe store the jakarta context on the Flowable ELContext instead of creating it always?

It is created once for each Flowable context instead of for every call.
@adityaanikam

Copy link
Copy Markdown
Author

Good point, thanks. The jakarta context is now stored on the Flowable ELContext and created once for each one. I added a test that checks it is reused for the same context

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intermittent EmptyStackException during CDI bean resolution with Weld and asynchronous jobs

3 participants