You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jspwiki.apache.org by Andrew Jaquith <an...@mac.com> on 2008/06/24 07:34:43 UTC
Shed light on how PageManager saves pages?
I have a few questions about the innards of JSPWiki and how it saves
pages. I suspect Janne and Murray know the answer to these.
As you know, I am investigating how to make workflows serializable.
For a given workflow to be serializable, it will likely require that
*everything* we stash in a Workflow also be serializable. In the
current PreSaveWikiPageTask, we stash a bunch of Strings plus the
WikiContext, then retrieve it later in SaveWikiPageTask. The
"SaveWikiPageTask" code is below.
// Retrieve attributes
WikiContext context = (WikiContext)
getWorkflow().getAttribute( PRESAVE_WIKI_CONTEXT );
String proposedText = (String)
getWorkflow().getAttribute( FACT_PROPOSED_TEXT );
WikiEngine engine = context.getEngine();
WikiPage page = context.getPage();
// Let the rest of the engine handle actual saving.
engine.getPageManager().putPageText( page, proposedText );
// Refresh the context for post save filtering.
engine.getPage( page.getName() );
engine.textToHTML( context, proposedText );
engine.getFilterManager().doPostSaveFiltering( context,
proposedText );
As you can see, we expect to be able to retrieve WikiContext as a
Workflow attribute called PRESAVE_WIKI_CONTEXT, which was stashed by
PreSaveTask.
My question is, is there anything special about the WikiContext that
we retrieve, which is passed to textToHTML() and
doPostSaveFiltering()? Could we create a synthetic one instead? In
other words, I am proposing that in PreSaveTask we stash the WikiPage
name as a string, then pick it up in SaveTask and use it to
manufacture a new, fake WikiContext with the correct WikiPage.
Why this could be important: if the WikiContext does not necessarily
need to be the original one (created by the user), that would mean we
wouldn't need to stick it in the Workflow. Which would make the "save
wiki page" workflow serializable.
Conversely, if the WikiContext used by textToHTML() and
doPostSaveFiltering() *has to be* the same WikiContext (and not
created synthetically), then we've got to keep stashing it as a
workflow attribute, and thus (here's the punchline)... we will never
to be able to persist workflows.
So, what do you think?
One more thing. Why do we call textToHTML() as part of the **save**
process? Here is what textToHTML() does (lightly edited):
boolean runFilters =
"true
".equals(m_variableManager.getValue(context,PROP_RUNFILTERS,"true"));
if( runFilters )
pagedata = m_filterManager.doPreTranslateFiltering( context,
pagedata );
result = m_renderingManager.getHTML( context, pagedata );
if( runFilters )
result = m_filterManager.doPostTranslateFiltering( context,
result );
I seem to recall something about needing to run textToHTML() so that
access rules and other meta-data were re-read correctly...
Andrew
Re: Shed light on how PageManager saves pages?
Posted by Janne Jalkanen <Ja...@ecyrd.com>.
> Thinking out loud: Might I recommend that we encourage plugin
> developers NOT to assume the presence of an HTTP request in 3.0?
> It's going to be much cleaner simply to grab whatever parameters
> Stripes binds to the ActionBean via their accessors (they will
> correctly typed, among other things). E.g., if Stripes binds the
> "page" request parameter to an ActionBean's property of type
> WikiPage, why not just use getPage() to get it, rather than go
> through trouble of getting the request from the context, calling
> getParameter(), looking for nulls and misspellings etc...? So much
> could go wrong, and Stripes takes care of this for you. So, in 3.0
> a developer commandment might be:
It's already the norm - check out the javadocs. For example,
embedders would not see a HttpServletRequest in there. We have a
getHttpParameter() which checks for HTTP parameters safely.
The point why it exists is that certain plugins (like WikiForms) can
this way communicate with each other across invocations.
> Aside: one of the things that pleases me the most about Stripes is
> that its parameter-binding glue allows us to decouple the request
> from the WikiContext. Likewise, the Resolution and related
> UrlBuilder classes decouple it from the response.
Ah, but Stripes parameter binding is static. You can't add new
parameters at runtime without resorting to reading the request.
>> Looking at the issues involved, I think it probably makes more
>> sense to stuff this to 3.0 and see if we can clarify the role of
>> the WikiContext a bit more. If WikiContext is going to be a
>> Stripes ActionBeanContext in the future, we've got to make sure
>> that is serializable too, of which I am not too sure about.
>
> I do not completely understand what you mean here, but I do not
> think that WikiContext should be serializable. Today, it contains
> references to too several things that have time-dependent states
> (HttpServletRequests go out of scope; HttpSessions expire, etc.).
> In the future, it would be extremely difficult to make WikiContexts/
> ActionBeans serializable because that would mean all of their
> properties would have to be serializable too. Not too hard with a
> concrete class, but probably impossible with an interface, which is
> what ActionBean is... would impede flexibility way too much.
Well, if you do want to serialize the state of the request across
workflows, then you might need to do that. We could add custom
serialization/deserialization code, which could go and create a
synthetic WikiContext when deserialized. What it would mean though
is global variables (i.e. singletons, like WikiEngine) which could be
accessed without knowledge of the context itself. So when
WikiContext is deserialized, it'll go and hydrate itself using
WikiEngine.getInstance(), etc. You will lose some information, but
that probably does not matter in the contexts that we will be using
it for (like workflows).
/Janne
Re: Shed light on how PageManager saves pages?
Posted by Andrew Jaquith <an...@mac.com>.
> Yup, we've got a problem. Most things in the WikiContext are such
> that they do not survive serialization - WikiEngine,
> HttpServletRequest, even WikiPage (due to interactions with the
> CachingManager).
>
> It's a good question whether they even do survive leaving the
> WikiSession and being executed in somebody else's context (the
> HttpServletRequest comes to mind). Now, since
> SavePageTask.execute() invokes the parser, that means that user
> plugins are also invoked, and if you've got someone relying on
> HttpServletRequest parameters at the time of save parsing - well,
> boom for them. (Not that I would see that anyone would do that.)
Oy.
Thinking out loud: Might I recommend that we encourage plugin
developers NOT to assume the presence of an HTTP request in 3.0? It's
going to be much cleaner simply to grab whatever parameters Stripes
binds to the ActionBean via their accessors (they will correctly
typed, among other things). E.g., if Stripes binds the "page" request
parameter to an ActionBean's property of type WikiPage, why not just
use getPage() to get it, rather than go through trouble of getting the
request from the context, calling getParameter(), looking for nulls
and misspellings etc...? So much could go wrong, and Stripes takes
care of this for you. So, in 3.0 a developer commandment might be:
Thy plugins shalt not assume that HttpServletRequests are available,
and shalt not parse its parameters.
In 2.8, clearly we **can't** make a "don't depend on the request"
recommendation...
Aside: one of the things that pleases me the most about Stripes is
that its parameter-binding glue allows us to decouple the request from
the WikiContext. Likewise, the Resolution and related UrlBuilder
classes decouple it from the response.
> The reason we call textToHTML() is to make sure the access rules and
> metadata are correct after save. This is needed because of the
> CachingProvider, and is one of the reasons why our metadata system
> is so crappy and kludgy and I can't wait to start fixing it in 3.0...
Hah! I knew it was something like that. It's never good to call a
method just because it has magic "side effects"; ideally we'd have a
non-kluge-y way to do thus... But there is no point in extracting the
magic bits from the renderer code that (in essence) do the metadata
refreshing. I completely agree that we can't solve this until 3.0.
> Looking at the issues involved, I think it probably makes more sense
> to stuff this to 3.0 and see if we can clarify the role of the
> WikiContext a bit more. If WikiContext is going to be a Stripes
> ActionBeanContext in the future, we've got to make sure that is
> serializable too, of which I am not too sure about.
I do not completely understand what you mean here, but I do not think
that WikiContext should be serializable. Today, it contains references
to too several things that have time-dependent states
(HttpServletRequests go out of scope; HttpSessions expire, etc.). In
the future, it would be extremely difficult to make WikiContexts/
ActionBeans serializable because that would mean all of their
properties would have to be serializable too. Not too hard with a
concrete class, but probably impossible with an interface, which is
what ActionBean is... would impede flexibility way too much.
Re: Shed light on how PageManager saves pages?
Posted by Janne Jalkanen <Ja...@ecyrd.com>.
> My question is, is there anything special about the WikiContext
> that we retrieve, which is passed to textToHTML() and
> doPostSaveFiltering()? Could we create a synthetic one instead? In
> other words, I am proposing that in PreSaveTask we stash the
> WikiPage name as a string, then pick it up in SaveTask and use it
> to manufacture a new, fake WikiContext with the correct WikiPage.
Yup, we've got a problem. Most things in the WikiContext are such
that they do not survive serialization - WikiEngine,
HttpServletRequest, even WikiPage (due to interactions with the
CachingManager).
It's a good question whether they even do survive leaving the
WikiSession and being executed in somebody else's context (the
HttpServletRequest comes to mind). Now, since SavePageTask.execute()
invokes the parser, that means that user plugins are also invoked,
and if you've got someone relying on HttpServletRequest parameters at
the time of save parsing - well, boom for them. (Not that I would see
that anyone would do that.)
> Conversely, if the WikiContext used by textToHTML() and
> doPostSaveFiltering() *has to be* the same WikiContext (and not
> created synthetically), then we've got to keep stashing it as a
> workflow attribute, and thus (here's the punchline)... we will
> never to be able to persist workflows.
Yes.
The reason we call textToHTML() is to make sure the access rules and
metadata are correct after save. This is needed because of the
CachingProvider, and is one of the reasons why our metadata system is
so crappy and kludgy and I can't wait to start fixing it in 3.0...
Looking at the issues involved, I think it probably makes more sense
to stuff this to 3.0 and see if we can clarify the role of the
WikiContext a bit more. If WikiContext is going to be a Stripes
ActionBeanContext in the future, we've got to make sure that is
serializable too, of which I am not too sure about.
/Janne