> The goal of this template is to remind you of many aspects that you could consider, to help you create a good concept.
> Tip: Use whichever sections are appropriate for the concept, delete the rest, rename and add at will, these are simply a suggestion.
> Tip: Delete all these comments.
We are reconsidering asynchronous execution and scheduling for the bigger refactoring of the UI. Things like Actions & Commands are reconsidered (see UI Bottom lift UI Action vs Platform commands and MGNLUI-3398 - Getting issue details... STATUS ). In case we have more multithreaded environments we start to have more issues with MgnlContext and JCRSessions. MgnlContext is a kind of singleton wrapper around WebContext or SimpleContext and keeps its state in thread-local or in other words request scope. The core issue is in the end the coupling between JCRSessions and the request scope which renders JCRSessions non sharable between multiple threads.
The simple solution to this would be to create JCRSessions only when actually used in for example the executor service. This is currently though not possible because important meta information like calling subject (user) etc is not shared over the call stack but only with the MgnlContext which is, as previously described, only shared in the request scope and like the JCRSession itself and therefore not sharable between threads.
Currently many parts of Magnolia rely on MgnlContext behaving the way it does like the JackrabbitAuthenticationModule which will pose additional challenges in the migration phase.
The general goal is to make Magnolias code executable in a multithreaded or asynchronous environment.
To enable this the following goals have to be achieved:
- Decouple the creation of JCRSessions from MgnlContext and scopes in general.
JCRSessions should be more a container around the execution of the business logic and not the whole dispatch of an action.
- Differentiate between the context of the call and the context of the scope. (We have here very a ambiguous topic as we probably have an overuse of the term 'context' in the system. So please don't think to hard of the current implementation and naming but rather focus on the intent in this text. You can help by finding better terminology for those new classes)
We have currently a mix of multiple concerns in our Context:
- Attributes related to the call of the business logic, like user, locale of the user, exception thrown during execution, etc. Those attributes are shareable between threads and can be handed along with the callstack to fulfill the intent of the original call.
- Attributes related to the session or request like aggregation state, servlet request and response, parameters, etc. Those attributes are not shareable.
- Utility methods like to get the JCRSession, access manager, messages, release resources etc. They should not be part of any context but should be injectable components, or have injectable providers.
We already have workarounds in place like in the CommandJob or would need workaround like in the PoC for Commands ( DEV-856 - Getting issue details... STATUS ) where we misuse the system context and fake to be another user or just life with incorrect data.
If implemented correctly, the CommandJob would not need to use the system context but would use the execution context. The CommandJob would pass the execution context along with the call and it, as well as any subsequent code in the stack is able to get a JCR Session, with correct authentication, with the information inside the execution context. As a reminder: the execution context is a very simple POJO and does not hold any special reference to resources like JCR.
We want to have clearly separated concerns for creating JCR Sessions, do authentication and storing context information about the call and the system. This will enable us to execute operations on JCR independently from the current scope like HTTP request.
To be able to do that we have to extract the creation of JCR sessions from the contexts, extract the different types of meta information about the call etc into specific new contexts (bad name because of preexisting terms ... if you have a better one please feel free to edit) and therefore hand the execution context along the call stack.
> AKA: Rationale
> Pros and Cons
> Consequences of this approach.
The first step will be to extract the the different concerns from the current MgnlContext, UserContext, WebContext, SystemContext, etc. This will lead to a better understanding of the the full scope of the problem.
We basically can have the following steps:
- Pick one of the concerns in the current contexts (like user information, session information, system information, etc)
- Extract that part into a new object and deprecate old code appropriately
- Ideally as part of that effort a good example use case is discovered which serves as testing ground and showcase
- Replace now the use of MgnlContext with the new objects.
- Repeat 1-3 for other concerns if possible
- Create a JCRSessionManager which will return the correct session according to the given new context info
- Replace the use of MgnlContext.getJCRSession() with the new JCRSessionManager
- Repeat 1-6 for different areas in the system.
> Describe concrete details of how the feature will be implemented. Could include class diagrams or interfaces.
- How heavily is MgnlContext used by customers and how big will the impact be of that change?
- How can we best mitigate the change?
> Possible Improvements
> Discarded Proposals