My initial feeling would be to make the JCR Session a part of the WikiContext (or, to be precise, a JCRWikiContext, which would be a concrete class which would implement a WikiContext interface). When the WikiContext is created, the Session is created too, and when the WikiContext expires, the Session is logged out. We could also add a WikiContext.save() method to flush all changes. This would provide fairly logical lifecycle management.

Hmm. I don't think this is a good idea. WikiContexts should really just be simple receptacles for form properties, plus some handler events that do things based on user actions. That is, they should be JavaBeans with some additional "verb" methods. (Or in Stripes parlance: ActionBean property getters and setters, plus event handler methods.) Putting JCR functionality into WikiContexts makes these things heavier, in my view, than they should be.

There are two potentially better places to locate JCR functionality. One place might be in the WikiSession, ideally as a property of the WikiSession (e.g., getRepositoryManager()/setRepositoryManager()). This is a pretty good place, actually, because WikiSession has privileged access to the JAAS Subject that contains the user's Principal set, and the user's private credentials (which we haven't exploited yet).

The other place would be the ActionBeanContext, which Stripes or WikiActionBeanFactory associates with every WikiActionBean/ WikiContext. Our implementation is tentatively called the WikiActionBeanContext (not suprisingly), and right now it doesn't do much more than the standard ActionBeanContext than contain a reference to the WikiEngine and WikiSession. We could certainly add JCR functions to that, as well.

So, those are my two suggested places.

The bad thing is that means that we need to carry WikiContext into quite a few places after that. Unless we turn WikiContext into the main repository interface as well, providing things like a Search interface as well. That means that it would inherit pretty much all of the functionality of the WikiEngine, which might make it a bit too unwieldy.

Remember that most of the "events" a user invokes that cause interesting things to happen will be done through event handler methods. Event handler methods are where the JSP scriptlet code will move to, and they will do most of the heavy lifting for business logic.

Also, WikiActionBean will be guaranteed to contain references to the WikiSession (as is the case today), or to the WikiActionBeanContext (as will be the case in 3.0). It would not be much work to do an extra getActionBeanContext().getRepositoryManager() and then invoke the functions that are needed.

My current idea is to turn WikiPages into essentially representatives of Nodes. Calling WikiPage.getContent() will return the content of the page and WikiPage.setContent() will set it. This provides a really neat way of managing the data, since e.g. WikiPage.get/setAttribute() could be automatically persisted. The bad thing, obviously, would be that since Nodes contain a reference to the Session where they came from, you *cannot* cache a WikiPage across new invocations (e.g. threads).

WikiPages == Node sounds good. We'll need to have a bit more discussion on the degree of auto-commit you foresee. I'm thinking in particular of the side-effects this might have if used in combination with the WikiPageTypeConverter (for 3.0), which will wire up and automatically set the correct WikiPage for a WikiActionBean based on the "page" parameter set in the request.

But beyond that, WikiPage.setContent()/getContent() sound like good places for persistence logic. PageManager might be good too. I tend to prefer data objects that are fairly stupid, and Manager classes that are smart.

Retaining the old WikiEngine API is problematic because the passed arguments only contain Strings. Since there is no session management in that API, we would need to do Repository.login() every time e.g. pageExists() is called, and *that* would become a bit too rough. So my preference would be, frankly, to dump existing WikiEngine API and make something nicer. We can have a lookalike API, but that's going to be slow.

WikiEngine should go on a diet. I'd like to see something really simple in 3.0. WikiEngine should just contains references to the major Manager classes, and eliminates convenience methods like saveText() and pageExists(), chiefly because they don't contain have method signatures with the right parameters. Certainly, if JCR needs "session awareness" we'll need to do a different API anyhow, so ditching the existing WikiEngine methods would be good.

PS. One more thought on WikiSession. The WikiSession's Subject would be a good place to stash the JCR credentials (username and password). I'm thinking, in particular, of Subject.setPublicCredentials() and Subject.setPrivateCredentials.

An obvious option would be to use a ThreadLocal for a Session, but that would pretty much make it a global, and the other problem is that then lifecycle management becomes a bit hazy - if there are unsaved changes, the session would grow uncontrollably. So there would need to be a separate flushing action at some point... But that would allow us to keep the existing API.

Well, we all know how important it is to have separate flushing actions. Otherwise, things would get messy indeed. <cough>

It might make sense to write a "JCR Monitor" similar to SessionMonitor, but for JCR sessions... perhaps something that "autosaves" or "autoflushes" every few minutes? This might be a good place to use JMX TimerMBean, too. (Actually, I'd kind of like to refactor the WikiBackgroundThread to be TimerMBeans, because the existing implementation doesn't always terminate cleanly... but that is another discussion...)

Any thoughts? Gotchas? Obvious ideas I've ignored? It would be a good idea if others read up on the JCR documentation as well - the spec is fairly well written, but it's quite long.

I wish I had the time. :)

Reply via email to