incubator-jspwiki-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Janne Jalkanen <Janne.Jalka...@ecyrd.com>
Subject Re: WikiActionBeans & context factories (changed subject from ClassUtil thread)
Date Sun, 27 Jan 2008 11:19:17 GMT
> If you are familiar with the Stripes concepts, you'll guess from  
> the preceding discussion that I'm recommending that we make  
> WikiContext analogous to a regular Stripes ActionBean. The nice  
> thing about regular old ActionBeans is that their APIs don't need  
> to be very complicated: just getters/setters for form fields, and  
> methods for "actions." Also the obligatory getActionBeanContext/ 
> setActionBeanContext.

I think this makes sense, because ActionBeans are not tied to the  
actual HttpServletRequest, and neither should WikiContext, which  
makes things like embedding possible in the first sense.

> It has been clear for a while that WikiContext needed to split  
> itself into multiple classes and interfaces. The most logical thing  
> to do is make WikiContext the general class or interface actions  
> that deal exclusively with pages. Therefore: WikiContext becomes an  
> abstract subclass of AbstractActionBean.

Why a concrete subclass?  Why not an interface?  I'm not advocating  
either, just wondering.

> The new class hierarchy for WikiContext and related types, for 3.0,  
> looks like this:
>
>     WikiActionBean extends ActionBean [Stripes]
>
>     AbstractActionBean implements WikiActionBean
>      |
>      +--WikiContext extends AbstractActionBean
>      |   |
>      |   +--ViewActionBean extends WikiContext
>      |   +--EditActionBean extends WikiContext
>     ... ... ...
>      +--GroupActionBean extends AbstractActionBean
>      |
>      +--UserPreferencesActionBean extends AbstractActionBean
>     ...
>
> [NOTE: it would be nice if we could deprecate "WikiContext" in  
> favor of, for example, "PageActionBean" to clearly denote that it's  
> about page activities. Maybe PageActionBean becomes the interface,  
> and we start coding to that...]

I am not totally sure of this.  I would very much like to keep our  
API signatures the same as much as possible, and that means lugging  
WikiContext around under the name "WikiContext".

Also, since GroupAction might also need to render something, or  
UserPreferences, you will need to invent a WikiContext for them as  
well.  So wouldn't it make sense to just make WikiContext ==  
AbstractActionBean?

Or more likely - make AbstractActionBean the concrete subclass, and  
WikiContext the interface towards lower layers.

> In 3.0, if you want to create a new ViewActionBean you can do it  
> via the zero-arg constructor [WikiContext context = new  
> ViewActionBean()] -- although you must immedidately also call  
> setActionBeanContext() and set the ActionBeanContext's WikiEngine  
> reference. It's much easier, instead, to call the factory method  
> WikiActionBeanFactory.newActionBean( WikiPage page), which does it  
> for you (see below).

I think I would like to introduce WikiContextFactory already in 2.8,  
and just deprecate the WikiContext constructors; then make them  
protected altogether in 3.0.

> - The setRequestContext() method disappears (it was only used in  
> like 5 places anyway), because the WikiContext subclasses *are* the  
> contexts. getReqeustContext() merely looks up a special JSPWiki  
> class-level annotation that specifies the context. (For example:  
> @WikiRequestContext("view"))

Yes, exactly.

Also, I'd like to resolve https://issues.apache.org/jira/browse/ 
JSPWIKI-117 somehow.  One of the ideas would be that we would have a  
proper WikiPage also associated with each action.

My idea is to leverage JSR-170, and put those pages in a special  
"System" -category, so we would have pages like "System/Login", or  
"System/NewGroup", which could be fully programmatical.  We would  
also deprecate SpecialPages for system pages and leave them for users  
to use as they please.  I like the fact that you can say, in  
wikitext, "You can login using the [System/Login] -page", instead of  
having to cut-n-paste the whole URL.

> - getCommand() goes away, as do the other Command-related methods.  
> Command interface is eliminated. It was a pretty dodgy idea to  
> begin with.

Yes, and it took me ages to understand. ;-)

> - hasAccess()/requiredPermission(). This are handled by our own  
> Stripes interceptor/controller (WikiInterceptor) in combination  
> with event-level annotations. So these methods should absolutely be  
> eliminated.

I am not totally certain of this.  There needs to be a way to ask the  
system "does user X has Y access to page Z?"  Maybe WikiContext is  
not the right place for them, but there needs to be a good, clear  
method for doing this.

> WikiActionBeans can be created in four ways:
>
> 1) Injection by UseActionBeanTag due to <stripes:useActionBean> tag  
> in JSP. This is the preferred way because it can be done with  
> little effort, and only requires single line at the top of a top- 
> level JSP:
>
> <stripes:useActionBean  
> beanclass="com.ecyrd.jspwiki.action.____ActionBean"/>

This is, IMO, really the only way.  Stripes documentation recommends  
another way, but in my experiments I found your way to be simply the  
best one.   Least confusion all around.

Stripes has a problem in the sense that the distribution of work  
between the ActionBean and the corresponding JSP page is not always  
clear.  Sometimes you use the JSP page as the entry point, sometimes  
the ActionBean (especially the validator tends to sometimes give the  
wrong URLs, exposing the underlying actions).

> Thus, when <stripes:useActionBean> is used in a JSP, the  
> WikiActionBean in question is guaranteed to have a non-null, valid  
> WikiActionBeanContext associated with it. This  
> WikiActionBeanContext, in turn, is guaranteed to return non-null  
> results for its getResponse/getRequest/getServletContext methods,  
> as well as its getWikiEngine and getWikiSession methods.

The question is, how do we deal with this when embedding; is it  
sufficient just to have a factory method which has an explicit  
argument for the WikiEngine / WikiPage?

> 2) Injection by DispatcherServlet due to POST/GET to /dispatcher, / 
> action/* or *.action URLs. This method appears to be used, in  
> particular, by generated Stripes form elements. It is rare that a  
> user would actually specify one of these URLs directly.

Yes, except for validation.  Stripes will automatically get you the  
*.action URL, if the content does not validate, which can be  
confusing.  I haven't yet found a way around this.

> In 3.0, Permissions are much more flexible because they are  
> annotation-driven. Moreover, they are specified at the method  
> level, NOT at the class (WikiContext) level. Because WikiContext  
> (and its subclasses) implement ActionBean, this is another way of  
> saying, "Permissions annotate methods that do things." For example,  
> consider ViewActionBean, which is a WikiContext subclass that  
> displays a wiki page. Its default event is the "view()" method,  
> which simply forwards control to itself and causes the page to  
> display. Here's the method signature:

Yes, I think using annotations for this is a great idea.  This does a  
lot of things automatically.

> Note the @EventPermission annotation. It defines the Permission  
> class and its target and actions. The "permissionClass" attribute  
> tells use that the Permission class this method needs is  
> "PagePermission". Note also the JSTL-style syntax in the target and  
> actions attributes -- these allow JSTL-access to bean properties  
> for the instantiated ViewActionBean. In this case, "${page}" is the  
> bean attribute that returns the value of this ViewActionBean's  
> getPage() method. The nested syntax "${page.qualifiedName}" is  
> equivalent to getPage().getQualifiedName(). Neat, huh?

The question is - does this JSTL mechanism work outside a HTTP context?

Reminds me, we also might want to stash the page and the WikiContext  
into the http request for brevity - it's a pain to always say "$ 
{actionBean.context.wikiContext.page.version}" - much easier to say "$ 
{page.version}".

BTW, I've been meaning to start a "JSPWiki 3.0 Design" page on  
jspwiki.org...  It might be a good idea to create one.

/Janne



Mime
View raw message