So this is somewhat of a topic larger than one PR.

First some background on architecture.  The ThreadContext is essentially an API 
wrapped around a ThreadLocal, designed to be the only thread local you actually 
need to track thread state.

In many other app servers some of us had worked on in the past, there tended to 
be a lot of ThreadLocals.  A big issue was state not getting cleaned up, 
resulting in it bleeding into other requests and other forms of leaks.  The 
unbreakable golden rule of our code base is ThreadContext.enter() and 
ThreadContext.exit() must be called in the same method, surrounded by a 
try/finally.  Enter before the try, and exit in the finally.  The second golden 
rule is a ThreadContext must be only associated with one thread at a time.

The ThreadContextListener API is how we populate and propagate thread state.  
These should be thread-safe.  Any objects copied from one ThreadContext to 
another should be thread-safe.

Now some strangeness I noticed in our code.

RequestScopedThreadContextListener was turned into a static field in 
CdiBuilder.  This is needless as the list of listeners in ThreadContext are 
already static.  Also, adding the same listener instance multiple times does 
nothing useful and creates a brief write lock on CopyOnWriteArraySet -- 
harmless, but also needless.  It causes no harm but is a code smell.

ThreadContextListener.contextEntered was changed to have a boolean propagateTx 
argument.  We should remove that as a parameter and make it an entry in the 
ThreadContext with a corresponding ThreadContextListener that adds it and 
propagates it and ideally facilitates the transaction propagation.  The default 
cannot be "true" as in EJB all asynchronous calls should NOT propagate 
transaction and security.  Propagation should be limited to the spec that 
requires it, which I think is Jakarta Concurrency scenarios.

Historically security and transaction state was not propagated to other threads 
in scenarios like async calls, because those things were inherently not thread 
safe.  The Geronimo TransactionManager is not capable of supporting a 
transaction across multiple threads.  To my knowledge it uses a ThreadLocal 
itself to track state and related code such as UserTransaction, 
TransactionSynchronizationRegistry and JTA as a spec are not capable for 
coordinating one transaction across multiple threads, nor are specs on top such 
as JPA.

We may need to review all the recent code that propagates state from one thread 
to another for async calls.  In most cases, the instances we propagate from one 
thread to another will likely not be thread-safe and need a major overhaul or 
complete rewrite unless they are fully read-only and immutable.

If you've added some code that propagates state in the last couple years, can 
you follow up with some details?  I'm happy to take a look and we can talk it 
through.  Double check it's safe.


-David

Reply via email to