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