RequestContextController spec impossible to implement
See original GitHub issueI’m not really happy with the RequestContextController. And it appears to me that the spec is broken.
Here is the important part from the spec:
6.5.2. Activating Built In Contexts Certain built in contexts support the ability to be activated and deactivated. This allows developers to control built-in contexts in ways that they could also manage custom built contexts. When activating and deactivating built in contexts, it is important to realize that they can only be activated if not already active within a given thread. 6.5.2.1. Activating a Request Context Request contexts can be managed either programmatically or via interceptor. To programmatically manage request contexts, the container provides a built in bean that is @Dependent scoped and of type RequestContextController that allows you to activate and deactivate a request context on the current thread. The object should be considered stateful, invoking the same instance on different threads may not work properly, non-portable behavior may occur. public interface RequestContextController { boolean activate(); void deactivate() throws ContextNotActiveException; } When the activate() method is called, if the request context is not already active on the current thread then it will be activated and the method returns true. Otherwise, the method returns false. When the deactivate() method is called, if this controller started the request context then the request context is stopped. The method does nothing if this controller did not activate the context
The problem is that there are 2 ways to use that part
a.)
boolean didActivate = reqCtxCtrl.activate();
...
if (didActivate) reqCtxCrl.deactivate();
b.)
try {
reqCtxCtrl.activate();
...
} finally {
reqCtxCrl.deactivate();
}
The problematic part is nesting. In case a) we got maybe 7 calls to activate() but only 1 to deactivate. In case b) we got 7 calls to activate and 7 to deactivate();
There is simply no way to implement this in a clean way. A simple boolean flag does not help because of concurrency. A ThreadLocal<List> does not help much either. If we use a ThreadLocal<Boolean> we potentially leak memory in case of a). If we close immediately we potentially close way too early in case b).
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:20 (16 by maintainers)
I mean – I believe that at this point, we conclusively established that RCC is possible to implement (contrary to this issue’s title). We also established that there are code patterns that make RCC usage safe.
We’re just debating problematic scenarios that stem from incorrect usage of RCC. That incorrectness stems from the nature of global state and has nothing to do with the CDI specification.
There are certainly ways how to improve the RCC API to make correct RCC usage easier. If we want to debate that, sure – I’m all for it.
@Ladicek no issue with the callback since nested calls will return a noop callback, this is how start/stop context are generally implemented in servers.
I’m not sure what you meant with “all the necessary provisions are already there” but since activate/deactivate javadoc are not consistent, the behavior is not so we’ll break applications/usage by clarifying it so thought a new API can make it less ambiguous but if you think we should reuse the one we have and enforce deactivate to not be called when false is returned it can work too with some risk (and to be honest i’m not sure how low or high it is).