Folks,
I've got a bit of a problem with respect to the JCR integration. I
will write a lengthy email explaining my current thoughts on the
subject partly to get your ideas, and partly to clarify my own
thoughts on the subject.
Our current model is stateless in the sense that the repository is
open all the time, and you just access the pages with a String handle
(pagename).
However, JCR model is stateful. That is you first get a Session
object, through which you manipulate the contents of the repository,
and once you're done, you release that object. This is similar to
Hibernate, though JCR Sessions are not threadsafe (and assumed to be
bound to a single Thread even, so they can't even be shared when
synchronized).
So logically we *could* have ContentManager have a single ThreadLocal
which keeps the Session object. However, since a Session gathers all
of the changes, it means that in case of e.g. exceptions, the old data
would still remain somewhere in the Session, and upon a new save, some
old, obsolete data would be saved as well. This is obviously not a
good thing.
No, we can't empty the Session with Session.refresh() before access
simply because we don't know when access begins - it could start even
with a simple getPage() - and obviously it's not a good thing if you
call getPage() multiple times during a single access.
So, it seems to me that in order to avoid side effects, we need to
have some sort of session management - which means acquiring a session
to the JSPWiki repository, and then also releasing it. The WikiEngine
object would be an obvious place for it, since it's what's being
passed around anyway.
So the proposal would be to have a WikiEngineFactory object, which you
would call as follows:
WikIEngine engine = WikiEngineFactory.getEngine();
try
{
WikiPage page = engine.getPage(...);
}
finally
{
engine.release();
}
The WikiPage object (and so the would not be valid after
engine.release().
Now, this does not mean that the Factory will create new WikiEngines,
but it'll probably set up some ThreadLocals so that it'll work
properly. If we had separate WikiEngine objects, we would need to
recreate all of our Manager classes. This unfortunately means that
WikiEngine is for all intents and purposes currently a singleton.
However, this approach would work, since you can't get to the managers
without getting a WikiEngine first.
Anybody see any serious problems with this approach? Anything that'll
break (other than every single plugin/Task which holds a reference to
a WikiPage or WikiContext object, but those can be refactored away)?
/Janne