You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jspwiki.apache.org by Janne Jalkanen <Ja...@ecyrd.com> on 2008/08/24 20:49:20 UTC
WikiContext & JCR Sessions
All (but especially Andrew),
JCR requires an object called a Session. This is very similar to
Hibernate's Session, in the sense that it represents actual read/
write access to the repository. The session gathers all the changes,
and those changes are then flushed all by calling Session.save().
The chief limitation is that Sessions are *not* thread-safe (and not
synchronized, for speed). However, Sessions are fairly fast to open
(JackRabbit is around 1.5 ms, Priha is faster).
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.
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.
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).
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.
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.
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.
/Janne
Re: WikiContext & JCR Sessions
Posted by Janne Jalkanen <Ja...@ecyrd.com>.
>> Reading this declaration hurts my head. :)
>
> This last declaration suggests that WikiContext ought to be a type
> of ActionBeanContext. I recall discussing that WikiContext was
> meant to be a superclass (or a marker interface) for page-oriented
> ActionBeans, rather than the ActionBeanContext. I.e., the
> relationship diagram would look like this:
My preference is strongly towards WikiContext being an interface. We
know already pretty well what is needed in it.
The idea really is that if someone wants to use JSPWiki as a basic
rendering engine, they can provide their own implementations of the
basic interfaces, without having to bring in the entire JSPWiki
WikiEngine and backend and stuff.
>
> However, it is not crazy to suggest that WikiContext could be a
> support class (like WikiActionBeanContext) rather than an
> ActionBean class itself. WikiContext shares several characteristics
> with WikiActionBeanContext: both need to set references to
> WikiEngine and WikiSession, and generally need to get at the
> request/response objects. That said, get/setWikiPage are better
> left in the ActionBean classes. WikiPage is really a property of
> the request, and in the HTTP scenario at least, would be bound by
> the magical Stripes request binder.
I think that WikiContext.getPage() *is* required, since it is used
practically everywhere, in all our plugins for example. If that
goes, we can pretty much kiss bye-bye to any attempt at making our
3rd party plugins somewhat easily compatible with 3.0...
Also, I would like to keep the name WikiContext.
The backend does not care whether it is a property of the request or
not - but it needs it in order to resolve relative paths and other
things. So I think that really does need to live on the WikiContext...
Perhaps there should be a superinterface of WikiContext (but a
subinterface of ActionBeanContext) which does not have the WikiPage?
That might have some limited use...
I think your second proposal was pretty good already :-)
/Janne
Re: WikiContext & JCR Sessions
Posted by Andrew Jaquith <an...@me.com>.
> WikiSession - contains user information and any thread-safe things
> which are expensive to create.
Yes.
>
> WikiActionBeanContext - encapsulates the basic info about the
> request. Does not require a WikiPage.
Yes.
>
> WikiContext - provides access to JSPWiki internals; lives exactly as
> long as an WikiActionBeanContext; requires a WikiPage.
Yes.
>
> RenderingContext - provides access to JSPWiki internals and
> rendering parameters; requires a WikiPage; thrown away after a chunk
> of wikimarkup is rendered.
>
> // Only bare minimum to make rendering work
> public interface RenderingContext
> {
> public WikiPage getPage();
> public WikiEngine getEngine();
> ...
> }
>
> // Extra context
> public interface WikiContext extends RenderingContext
> {
> public HttpServletRequest getRequest(); // This already exists.
> ...
> }
Makes sense. However, see my comments below.
>
>
> public class WikiActionBeanContext
> {
> public WikiSession getSession();
> public WikiEngine getEngine();
> public HttpServletRequest getRequest();
> public HttpServletResponse getResponse();
> }
Yes.
> public class WikiPageActionBeanContext extends WikiActionBeanContext
> implements WikiContext
> {
> ...
> }
>
Reading this declaration hurts my head. :)
This last declaration suggests that WikiContext ought to be a type of
ActionBeanContext. I recall discussing that WikiContext was meant to
be a superclass (or a marker interface) for page-oriented ActionBeans,
rather than the ActionBeanContext. I.e., the relationship diagram
would look like this:
1) Support classes -- used by ActionBeans
ActionBeanContext
--> sets/gets HttpServletRequest
--> sets/gets HttpServletResponse
WikiActionBeanContext
--> extends ActionBeanContext
--> gets/sets WikiEngine
--> gets/sets WikiSession
2) ActionBean classes
ActionBean
--> gets/sets ActionBeanContext
--> gets/sets request parameters submitted by user
WikiActionBean (interface) + AbstractWikiActionBean (abstract class)
--> extends ActionBean
--> sets/gets WikiActionBeanContext
--> contains much of today's WikiContext implementation code:
e.g., get/set variables
WikiContext (abstract class)
--> implements WikiActionBean
--> extends AbstractWikiActionBean
--> gets/sets WikiPage
--> gets/sets HttpRequest (which forwards to WikiActionBeanContext)
ViewActionBean (concrete class)
--> extends WikiContext
--> gets/sets version
--> contains "view" handler method
However, it is not crazy to suggest that WikiContext could be a
support class (like WikiActionBeanContext) rather than an ActionBean
class itself. WikiContext shares several characteristics with
WikiActionBeanContext: both need to set references to WikiEngine and
WikiSession, and generally need to get at the request/response
objects. That said, get/setWikiPage are better left in the ActionBean
classes. WikiPage is really a property of the request, and in the HTTP
scenario at least, would be bound by the magical Stripes request binder.
The re-worked hierarchy would look like this:
1) Support classes -- used by ActionBeans
ActionBeanContext -- same as before
--> sets/gets HttpServletRequest
--> sets/gets HttpServletResponse
WikiActionBeanContext -- changed. (Could also be called WikiContext)
--> extends ActionBeanContext
--> gets/sets WikiEngine
--> gets/sets WikiSession
--> contains much of today's WikiContext implementation code:
e.g., get/set variables
2) ActionBean classes
ActionBean -- same as before
--> gets/sets ActionBeanContext
--> gets/sets request parameters submitted by user
WikiActionBean -- same as before
--> extends ActionBean
--> sets/gets WikiActionBeanContext
ViewActionBean (concrete class) -- changes slightly
--> extends WikiContext
--> gets/sets WikiPage
--> gets/sets version
--> contains "view" handler method
> So the basic idea would be that we use the Wiki/RenderingContext as
> interfaces announcing what kind of functionalities are required, and
> use the ActionBeanContext classes to implement these. Or maybe they
> should be ActionBeans, I am not too sure (and I'm too lazy right now
> to snap the code out of SVN ;-)
>
> (The rendering code can then check whether it has a full WikiContext
> or just a RenderingContext, and then function accordingly.)
>
> /Janne
Re: WikiContext & JCR Sessions
Posted by Janne Jalkanen <Ja...@ecyrd.com>.
>
> ActionBeanContext is really just meant to encapsulate HTTP request
> state. (From the Stripes Javadoc: "Encapsulates information about
> the current request. Also provides access to the underlying Servlet
> API should you need to use it for any reason.") The
> ActionBeanContext is just a property of an ActionBean, and it can
> be set or get freely.
>
> Rendering might well be one of those concerns that should be
> cleanly separated from HTTP. In fact, it probably should be.
> However, don't think we should build rendering functions into
> WikiContext directly. A property that allows the rendering context
> to be obtained, similar to how the HTTP context can be obtained via
> getContext(). Maybe getRenderingContext()? Making accessible via a
> delegate method is probably a lot cleaner than building it into an
> abstract superclass.
>
> What kinds of functionality do you foresee RenderingContext needing?
Well, RenderingContext needs to provide page context information
(i.e. getWikiPage()) for example to determine the real URLs for any
relative links, as well as page variables. So it sounds like it
should be a relative of WikiContext. It should also have pretty
broad access (e.g. to determine variable values from the HttpRequest,
so it might need access to that, too). Also, if any plugins exist on
the page, they *will* need access to the full WikiContext. Also, the
idea would be that someone who only wants the JSPWiki rendering
capability can pass their own RenderingContext to it, so it should be
fairly simple.
Agree on that we don't want to put the rendering stuff into
WikiContext. It would only confuse things. Making it available via
a factory or a delegate method is probably the best idea (with slight
preference to the factory, because then it can be made independent of
other structures).
So, we have...
WikiSession - contains user information and any thread-safe things
which are expensive to create.
WikiActionBeanContext - encapsulates the basic info about the
request. Does not require a WikiPage.
WikiContext - provides access to JSPWiki internals; lives exactly as
long as an WikiActionBeanContext; requires a WikiPage.
RenderingContext - provides access to JSPWiki internals and rendering
parameters; requires a WikiPage; thrown away after a chunk of
wikimarkup is rendered.
// Only bare minimum to make rendering work
public interface RenderingContext
{
public WikiPage getPage();
public WikiEngine getEngine();
...
}
// Extra context
public interface WikiContext extends RenderingContext
{
public HttpServletRequest getRequest(); // This already exists.
...
}
public class WikiActionBeanContext
{
public WikiSession getSession();
public WikiEngine getEngine();
public HttpServletRequest getRequest();
public HttpServletResponse getResponse();
}
public class WikiPageActionBeanContext extends WikiActionBeanContext
implements WikiContext
{
...
}
So the basic idea would be that we use the Wiki/RenderingContext as
interfaces announcing what kind of functionalities are required, and
use the ActionBeanContext classes to implement these. Or maybe they
should be ActionBeans, I am not too sure (and I'm too lazy right now
to snap the code out of SVN ;-)
(The rendering code can then check whether it has a full WikiContext
or just a RenderingContext, and then function accordingly.)
/Janne
Re: WikiContext & JCR Sessions
Posted by Andrew Jaquith <an...@me.com>.
>> required ActionBean method getContext()). The WikiActionBeanContext
>> itself contains only four references: for WikiEngine, WikiSession,
>> HttpServletRequest and HttpServletResponse. That's it -- no other
>> references to Stripes objects, and no long chains of object
>> references pulling in lots of heavyweight stuff.
>
> Well, that looks good - except for the HttpServletRequest/Response.
> Those are dependent on this all being a HTTP application (which may
> not be true if you embed the rendering engine in some app). But on
> the other hand, we can of course state that those *can* be null in
> certain cases, or substitute dummy values (which in turn make these
> again Stripes-dependent).
To avoid NPEs, I take the position that HttpServletRequest/Response
references must always be set when a WikiContext/WikiActionBeans are
created, even if the caller doesn't (or cannot) supply any. In other
words, we create some dummy objects (Stripes MockHttpServletRequest/
Response objects actually). Take a look at
WikiActionBeanFactory.newInstance() in ARJ_STRIPES_BRANCH....
Is this sort of thing a kluge? Yes. Does it make us dependent on
Stripes? No, because there aren't any references made or kept to
Stripes classes other than the ActionBeanContext subclass itself
(WikiActionBeanContext). It's more, as you point out, a dependency on
HTTP.
> I'm not worried about HTTP requests, I'm worried about cases
> *outside* HTTP (still trying to think separation of rendering and
> the rest).
Got it...
> What is the real relationship between WikiContext and
> WikiActionBeanContext? For rendering, I think we need a separate
> RenderingContext interface, which encapsulates everything that the
> rendering engine needs into one interface. But I am currently
> unsure as to how all these should relate to each other.
ActionBeanContext is really just meant to encapsulate HTTP request
state. (From the Stripes Javadoc: "Encapsulates information about the
current request. Also provides access to the underlying Servlet API
should you need to use it for any reason.") The ActionBeanContext is
just a property of an ActionBean, and it can be set or get freely.
Rendering might well be one of those concerns that should be cleanly
separated from HTTP. In fact, it probably should be. However, don't
think we should build rendering functions into WikiContext directly. A
property that allows the rendering context to be obtained, similar to
how the HTTP context can be obtained via getContext(). Maybe
getRenderingContext()? Making accessible via a delegate method is
probably a lot cleaner than building it into an abstract superclass.
What kinds of functionality do you foresee RenderingContext needing?
Andrew
Re: WikiContext & JCR Sessions
Posted by Janne Jalkanen <Ja...@ecyrd.com>.
> Are you sure they are stashed in the HttpSession? The original
> implementation I wrote took great care to make sure that they
> weren't. That MIGHT have changed due to a bug fix, but I just took
> a look at SessionMonitor and WikiSession, and I could not find when
> WikiSession was actually stashed. A quick reference-skim for
> HttpSession.setAttribute() didn't turn up anything either.
Well, okay, not really stashed into HttpSession, but SessionManager
stores them by using the HttpSession as a key. So they will be
called from multiple threads, though not at the same time.
Regardless, it's not an optimal solution.
> required ActionBean method getContext()). The WikiActionBeanContext
> itself contains only four references: for WikiEngine, WikiSession,
> HttpServletRequest and HttpServletResponse. That's it -- no other
> references to Stripes objects, and no long chains of object
> references pulling in lots of heavyweight stuff.
Well, that looks good - except for the HttpServletRequest/Response.
Those are dependent on this all being a HTTP application (which may
not be true if you embed the rendering engine in some app). But on
the other hand, we can of course state that those *can* be null in
certain cases, or substitute dummy values (which in turn make these
again Stripes-dependent).
> I'm NOT actually trying to argue that WikiActionBeanContext is the
> right place to put the JCR code (or a reference to a class that
> contains it) -- just pointing out that it's not as heavyweight as
> you might think. It will always be available, which makes it a
> decent place to put stuff. And a new one is created, fresh, for
> every HTTP request.
I'm not worried about HTTP requests, I'm worried about cases
*outside* HTTP (still trying to think separation of rendering and the
rest).
What is the real relationship between WikiContext and
WikiActionBeanContext? For rendering, I think we need a separate
RenderingContext interface, which encapsulates everything that the
rendering engine needs into one interface. But I am currently unsure
as to how all these should relate to each other.
/Janne
Re: WikiContext & JCR Sessions
Posted by Andrew Jaquith <an...@me.com>.
(Janne -- you should interpret my comments, below, as informational
rather than argumentative. Use, or not, as you see fit.)
> WikiSession does not work, because WikiSessions are shared across
> threads (they're stashed in the HttpSession), and therefore it is
> illegal to put Sessions in there. WikiSessions also live too long.
Are you sure they are stashed in the HttpSession? The original
implementation I wrote took great care to make sure that they weren't.
That MIGHT have changed due to a bug fix, but I just took a look at
SessionMonitor and WikiSession, and I could not find when WikiSession
was actually stashed. A quick reference-skim for
HttpSession.setAttribute() didn't turn up anything either.
> I am not sure about that, since that would mean that any and all
> backend methods suddenly need to become Stripes-aware, and that is
> simply just leaking too much information across boundaries. It will
> also make life of the embedders annoying, when they just want to
> render content, and they need to carry the entire ActionBean legacy
> from Stripes into their code - when they really don't even need it.
That's a good point. But, the Stripes stuff that is referenced by
WikiContexts/WikiActionBeans is pretty minor, though. And because of
the way I've had to retrofit it into our existing classes, it is done
in a way that is transparent to the rest of JSPWiki. The contract is,
basically, that if a WikiContext is created through any of the four
possible methods (StripesFilter, useActionBean tag,
WikiEngine.createContext() or WikiActionBeanFactory.newActionBean()),
it will be guaranteed to have a non-null WikiActionBeanContext made
available to it (via the required ActionBean method getContext()). The
WikiActionBeanContext itself contains only four references: for
WikiEngine, WikiSession, HttpServletRequest and HttpServletResponse.
That's it -- no other references to Stripes objects, and no long
chains of object references pulling in lots of heavyweight stuff.
(I've written up the approach in the "doc/README - Stripes Migration"
file, in ARJ_STRIPES_BRANCH.)
I'm NOT actually trying to argue that WikiActionBeanContext is the
right place to put the JCR code (or a reference to a class that
contains it) -- just pointing out that it's not as heavyweight as you
might think. It will always be available, which makes it a decent
place to put stuff. And a new one is created, fresh, for every HTTP
request.
> ONLY when we are talking about a http context. Embedders, or say,
> even RSS generation internally, would not have it (and would need
> the DummyHttpRequest & others).
You can still execute handler methods outside of Stripes. What you
won't get are the automatic property binding and validation features.
But event methods should still work fine. And more to the point,
handler methods can return any type they want or throw Exceptions.
That makes them useful in non-Stripes contexts.
Also, the WikiActionBeanFactory methods for creating new WikiContexts/
ActionBeans, by necessity, create a backing WikiActionBeanContext
object and mock request/response objects, if not supplied by callers.
This allows for backwards compatibility with
WikiEngine.createContext() -- critical for JSP migration. That is
really all the event handler methods need to function properly.
>> 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.
>
> Did you take a look at the current WikiEngine in the API proposal?
> It's *very* lean. Too lean, in fact...
I am overdue in looking at this... :)
Re: WikiContext & JCR Sessions
Posted by Janne Jalkanen <Ja...@ecyrd.com>.
> 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).
WikiSession does not work, because WikiSessions are shared across
threads (they're stashed in the HttpSession), and therefore it is
illegal to put Sessions in there. WikiSessions also live too long.
> 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.
I am not sure about that, since that would mean that any and all
backend methods suddenly need to become Stripes-aware, and that is
simply just leaking too much information across boundaries. It will
also make life of the embedders annoying, when they just want to
render content, and they need to carry the entire ActionBean legacy
from Stripes into their code - when they really don't even need it.
The JCR Session object is purely and only related to the Model tier,
so mixing View or Controller stuff to it sounds icky.
> 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.
ONLY when we are talking about a http context. Embedders, or say,
even RSS generation internally, would not have it (and would need the
DummyHttpRequest & others).
> 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.
I'm not seeing any autocommit there. All changes need a separate
commit() [or in JCR lingo, save()].
> 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.
Me too, usually - it's just that in this case, once the WikiPage
contains a reference to the Node, we've pretty much lost the game :-)
> 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.
Did you take a look at the current WikiEngine in the API proposal?
It's *very* lean. Too lean, in fact...
But the point is really that we can create a special, self-contained
API JAR, which we can say "this is now the public API which won't be
changed". This means that even the WikiEngine interface cannot
expose too much internals. (You can always then get a WikiEngineImpl
for hacking.)
> 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.
Mmm... Well, JCR credentials != JSPWiki credentials. We will need to
put in the credentials in the property file anyway (in order to allow
the engine itself access to the repository outside a Http request,
e.g. indexing or whatever). I don't think that the JCR auth system
is very good for us anyway, since it's too restrictive. I wasn't
planning on using it.
> 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...)
Well, if we keep a JCR Session open through only a single HTTP
Request (remember, they're cheap to create, and this seems to be the
recommended way at least from the Jackrabbit people), there is no need.
/Janne
Re: WikiContext & JCR Sessions
Posted by Andrew Jaquith <an...@me.com>.
> 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. :)