For the modify/write case, any of the set() methods store local,
uncommitted changes in the WikiPage object. The save() method starts a
new Session and commits. Or maybe any of set() methods start a new
transaction which is held open until the save().

...but then we need to code in lots of redundant stuff which is already managed by JCR.

Consider the following case:

WikiPage page = getPage(...);
page.setAttribute("foo","bar");
page.save();

page.setAttribute("foo","blob");

String attr = page.getAttribute("foo");

The value of "attr" should obviously be "blob" instead of "bar". This means that WikiPage will internally need to check the stuff from a local cache before it fetches it from JCR. This is an extra hit on all getAttribute() requests.

In addition, we need to build a disk cache, managed by WikiPage for Really Large Binaries, including deletion when WikiPage is garbage collected, etc (unless we want to cache them in memory, which is something we probably don't want to do). Of course a ready cache library can be used to do that, but again, it feels a bit pointless when JCR does it for us.

Basically, the idea is to make read-only access very cheap, but writes
more expensive... and to hide all of the state management details from
callers.

I don't think we can; imagine a situation where we have something like this:

WikiPage page = getPage(...)

page.setAttribute("foo","bar");

doThingy(page);

...

public doThingy(WikiPage page) throws Exception
{
   page.setAttribute("bar", "baz");
}

Now, if doThingy() throws an exception, it needs to do its own state management to clean things up before it passes it up to the caller, or else the state of the page is undefined when it goes up.

So we already have to do state management.

Originally, I was planning to tie state management into WikiContext's lifecycle, but I realized that it's a bit complicated because then everything needs a WikiContext either passed around or created, and that's a bit of a problem.

However, when Session management is done with WikiEngine, it means that the only case where you really have to care about this is when you *originally* fetch a WikiEngine. This is typically done only in WikiServletFilter, or in the case of embedders, when you start a session (=get a WikiEngine).

In addition, having a proper lifecycle means that the JCR Session can be released by the JCR engine when it is not used. If the ContentManager just holds on to the Session, it'll just keep consuming resources. Probably not a lot, but it's still something.

My thinking on this has been influenced by Alfresco. Here are some
interesting notes about what they are doing:

http://wiki.alfresco.com/wiki/Introducing_the_Alfresco_Java_Content_Repository_API
http://wiki.alfresco.com/wiki/Java_Foundation_API

As you can see from their examples, they also have state management. They just create a new Session in the beginning (Repository.login()), do their thing, and then finally call Session.logout().

This is a common pattern, used also by other content management interfaces such as Hibernate.

/Janne

Reply via email to