Author: ajaquith
Date: Thu Aug 7 20:14:33 2008
New Revision: 683817
URL: http://svn.apache.org/viewvc?rev=683817&view=rev
Log:
Beginning of Stripes JSP-tier refactoring.
Added:
incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/README - Stripes
Migration
- copied, changed from r682162,
incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/Java 5 changes
Removed:
incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/Java 5 changes
Copied: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/README -
Stripes Migration (from r682162,
incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/Java 5 changes)
URL:
http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/README%20-%20Stripes%20Migration?p2=incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/README%20-%20Stripes%20Migration&p1=incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/Java%205%20changes&r1=682162&r2=683817&rev=683817&view=diff
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/Java 5 changes
(original)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/doc/README - Stripes
Migration Thu Aug 7 20:14:33 2008
@@ -1,21 +1,171 @@
-Eclipse... Software Update
-New Remote Site:
-Name: Findbugs
-URL: http://findbugs.cs.umd.edu/eclipse
+MIGRATION GUIDE FOR JSP DEVELOPERS
+==================================
-Name: CheckStyle Eclipse Plug-in
-URL: http://eclipse-cs.sourceforge.net/update
+Required changes:
+- Stripes Tags. Add Stripes packages and imports to JSPs
+- WikiContext Creation. All top-level JSPs that create non-page-related
WikiContexts must use the <stripes:useActionBean> tag instead of
createContext().
+- JSP Content Pages. When JSP content templates (*Content.jsp) don't use the
default name, JSP authors will be required to supply it.
+
+Recommended changes:
+- Setting WikiContext request attribute directly is discouraged. JSPs should
not set the WikiContext or WikiSession as a request attribute, and is
discouraged.
+- Parsing request parameters is discouraged. Setting request attributes should
use WikiActionBean accessors instead of parsing request parameters directly.
+- <fmt:setBundle> no longer needed. JSPWiki's web.xml now sets the default
bundle name (templates.default) for JSP <fmt:> tags.
+
+Enhancements:
+- JSP Page Variables. The current WikiContext and other objects are now saved
automatically as request attributes, and are available to JSPs as JSTL
variables 'wikiContext,' 'wikiActionBean,' 'wikiEngine,' and 'wikiSession.'
+
+
+REQUIRED CHANGES
+
+
+Stripes Tags
+------------
+Add Stripes packages and imports to JSPs.
+
+What JSP authors must do:
+Include these lines for all top-level JSPs:
+
+<%@ page import="com.ecyrd.jspwiki.action.*" %>
+<%@ taglib uri="/WEB-INF/stripes.tld" prefix="stripes" %>
+
+WikiContext Creation
+--------------------
+All top-level JSPs that create non-page-related WikiContexts must use the
<stripes:useActionBean> tag instead of createContext().
+
+What JSP authors must do:
+For login, group, workflow and other contexts that do not operate on
WikiPages, replace lines like these:
+
+ WikiContext wikiContext = wiki.createContext( request, WikiContext.LOGIN );
+
+...with these:
+
+<stripes:useActionBean beanclass="com.ecyrd.jspwiki.action.LoginActionBean"/>
+
+To retrieve the WikiActionBean later, scriptlet code should call this static
method:
+
+ WikiActionBean wikiContext = WikiActionBeanFactory.findActionBean( request
);
+
+Background: WikiEngine.createContext() still works for those cases where
creating a WikiContext (page-style ActionBean) is needed. In JSPWiki 3.0,
WikiContext becomes an interface for WikiActionBeans that handle page viewing,
editing, preview, diffs, etc. Thus, calls to WikiEngine.createContext() still
work fine because the method is expected to return a WikiContext. But for other
ActionBeans (e.g., LoginActionBean), WikiEngine.createContext() will not work
because the return type is a WikiContext rather than the more generic
WikiActionBean type that is required. Instead, scriptlet code should use
<stripes:useActionBean> tag.
+
+Note that every time <useActionBean> or createContext() is called, the
request's "current" is re-set, which effectively over-writes previous values.
+
+Note: JSPs that create these (pre-3.0) WikiContexts will need to be changed:
+ADMIN, CREATE_GROUP, DELETE_GROUP, EDIT_GROUP, ERROR, FIND, INSTALL, LOGIN,
LOGOUT, MESSAGE, NONE, OTHER, PREFS, RSS, VIEW_GROUP, WORKFLOW.
+
+Scriptlet code
+--------------
+Move JSP scriptlet code to ActionBean event handlers
+
+What JSP authors must do:
+(instructions go here)
+
+JSP Content Pages
+-----------------
+When JSP content templates (*Content.jsp) don't use the default name, JSP
authors will be required to supply it.
-Class Hierarchy
+What JSP authors must do:
+Add a line to scriptlet code similar to the following to the top-level JSP:
+
+ wikiContext.setVariable( "contentTemplate", "PageContent.jsp" );
+
+Background: Because the hard-coded Command classes are gone in JSPWiki,
JSPWiki now calculates a default content template name. The content JSP is
automatically calculated as the simple bean name, minus "ActionBean", plus
"Content.jsp." Thus, the default for ViewActionBean.jsp would be
ViewContent.jsp. This works in most cases, but not, for example, with Wiki.jsp
(the content template is PageContent.jsp, not WikiContent.jsp).
+
+To override the default behavior, add a line similar to this to top-level
JSPs, ideally right before the wiki:Include tag:
+
+ wikiContext.setVariable( "contentTemplate", "PageContent.jsp" );
+
+The 'contentTemplate' variable value will be read, downstream, by ContentTag
when including the contents.
+
+Forms and form fields
+---------------------
+Migration to Stripes tags:
+
+stripes:form. must change accept-charset to acceptcharset
+
+
+RECOMMENDED CHANGES
+
+Setting WikiContext request attribute directly is discouraged
+-------------------------------------------------------------
+JSPs should not set the WikiContext or WikiSession as a request attribute, and
is discouraged.
+
+What JSP authors must do:
+Lines like these:
+
+ request.setAttribute( WikiTagBase.ATTR_CONTEXT, wikiContext );
+
+should be removed. This seems to be a factor ONLY in two JSPs: Message.jsp and
Workflow.jsp.
+
+Background: WikiInterceptor and WikiEngine.createContext() now assume sole
responsibility for making the WikiContext available as a request attribute.
+
+Parsing request parameters is discouraged
+-----------------------------------------
+Setting request attributes should use WikiActionBean accessors instead of
parsing request parameters directly.
+
+What JSP authors must do:
+Stripes automatic parameter-binding system makes parsing request parameters
unneccessary. Stripes will also automatically perform type conversion between
the supplied parameter (always String or String[]) to the desired target type,
based on the WikiActionBean property type. Thus, lines like these:
+
+ request.setAttribute( "message", request.getParameter("message"));
+
+should be changed to:
+
+ request.setAttribute( "message", messageActionBean.getMessage());
+
+<fmt:setBundle> no longer needed
+--------------------------------
+JSPWiki's web.xml now sets the default bundle name (templates.default) for JSP
<fmt:> tags.
+
+What JSP authors must do:
+Remove these lines from JSPs:
+
+<fmt:setBundle basename="templates.default"/>
+
+URL redirects
+-------------
+General behaviors need to change in the JSP layer so that instead of looking
up a URL and then calling redirect directly, we need instead to obtain
RedirectResolutions.
+
+
+ENHANCEMENTS
+
+JSP Page Variables
+------------------
+The current WikiContext and other objects are now saved automatically as
request attributes, and are available to JSPs as JSTL variables 'wikiContext,'
'wikiActionBean,' 'wikiEngine,' and 'wikiSession.'
+
+What JSP authors must do:
+Nothing. Assuming the WikiActionBean was created and resolved correctly, these
four variables (wikiContext, wikiActionBEan, wikiEngine and wikiSession) are
all available "for free" by JSPs.
+
+Details: in previous versions of JSPWiki, top-level JSPs were required to
stash the WikiContext into request scope using either scriptlet code similar to
this:
+
+request.setAttribute( WikiTagBase.ATTR_CONTEXT, this );
+
+JSPs could also call WikiContext.hasAccess() and the save would be done
automatically. In 3.0, however, responsibility for stashing the WikiContext now
belongs to the Stripes WikiInterceptor and/or WikiEngine.createContext(). All
that is require is that any of these three conditions be true: 1) the JSP calls
WikiEngine.createContext(), 2) the JSP invokes the <stripes:useActionBean> tag,
or 3) the JSP is invoked indirectly by a Stripes ActionBean handle method.
+
+In all three cases, the current WikiActionBean is saved as the variable
'wikiActionBean'. If the WikiActionBean is *also* a WikiContext, the it is also
saved as the variable named WikiTagBase.ATTR_CONTEXT ('wikiContext'). This is
essentially unchanged from before. Also, if the WikiActionBean is *not* a
WikiContext, to preserve backwards compatibility a fake WikiContext (a
ViewActionBean that points to the front page) is saved instead. Thus, the JSTL
variable 'wikiContext' will always be present.
+
+The addition of JSTL variables makes JSP scripting much simpler. For example,
scriptlet code in JSPs that needs to obtain a reference to the WikiEngine can
simply use ${wikiEngine}.
+
+This means...
+<%
+ WikiContext c = WikiContext.findContext(pageContext);
+ WikiPage wikipage = c.getPage();
+%>
+...can simply be replaced by ${wikiContext.page}.
+
+
+API Changes
+===========
+
+WIKIACTIONBEANS
---------------
+
+Background
+----------
WikiContext is the all-singing, all-dancing "request context" class in
JSPWiki. It encapsulates the idea of "doing a wiki activity": viewing a page,
editing a group, commenting, etc. In Stripes parlance, these are what you'd
call "ActionBeans."
WikiContext was originally conceived to encompass everything and everything
you might want to do to a wiki page. In JSPWiki 2.4 and higher, WikiContext got
overloaded with lots of activities that have nothing to do with pages, like
creating groups and registering.
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.
-Note that because WikiContext becomes abstract, we need to change all of the
direct instantiations of WikiContext. So, what I've done is created a
WikiContext subclass (a Stripes ActionBean, in fact) called ViewActionBean that
is for the "view page" context.
-
The new class hierarchy for WikiContext and related types, for 3.0, looks like
this:
WikiActionBean extends ActionBean [Stripes]
@@ -30,86 +180,77 @@
+--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...]
-
-The new class structure means that techniques for creating WikiContexts will
change. Old instantiations of WikiContext looked like this:
-
-WikiContext dummyContext = new WikiContext( m_engine, m_context.getPage() );
-
-WikiContext dummyContext = new WikiActionBean( m_engine, m_context.getPage() );
-
-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).
+ ...
-Other significant changes to WikiContext:
+WikiActionBeans are the core action class in JSPWiki 3.0. All WikiActionBeans
are expected to adhere to the following contract:
+- must have a zero-argument constructor
+- must set the ActionBeanContext immediately after instantiation (setContext)
+- must set the associated ActionBeanContext's WikiEngine immediately after
instantiation (setWikiEngine)
+- must return non-null HttpServletRequest and HttpServletResponse objects,
either via WikiActionBean methods or via
WikiActionBeanContext.getRequest/getResponse.
-- 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"))
+Note that because WikiContext becomes abstract, it is not possible to create
them directly any more. See the next section for details on how to create them.
-- WikiContext.getCommand() goes away, as do the other Command-related methods.
Command interface is eliminated. It was a pretty dodgy idea to begin with.
+Creating WikiActionBeans
+------------------------
+WikiActionBeans can be created in five ways:
-- getLocale(). Not used in JSPs or core code. Because Stripes takes care of a
lot of this, it's not needed.
+1) Injection by UseActionBeanTag due to <stripes:useActionBean> tag in JSP.
This is the preferred way because it can be done with only a single changed
line at the top of a top-level JSP:
-- 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.
+<stripes:useActionBean beanclass="com.ecyrd.jspwiki.action.____ActionBean"/>
-WikiActionBean Security
------------------------
-In 2.4, security permissions were added to WikiContexts. Each WikiContext
could specify what Permission a user needed to access that context by causing
the method requiredPermission() to return a value. This worked well, although
it required each WikiContext type ("view","edit" etc.) to figure out a way to
express the Permission through code. This, in part, was what let to the
disaster that is the Command class.
+Technically, the WikiActionBean is looked up by Stripes' configured
ActionResolver (by default, the AnnotatedClassActionResolver); the bean itself
is instantiated using its zero-argument constructor. Stripes guarantees that
the following things happen after instantiation, as part of its
ActionBeanResolution lifecycle stage:
+- The WikiActionBean's setActionBeanContext() method is called (by
AnnotatedClassActionResolver); this causes a reference to a new
WikiActionBeanContext to be set in the WikiActionBean
+- The WikiActionBeanContext's setServletContext() method is called (by
UseActionBeanTag); this sets an internal reference to the WikiEngine
+- The WikiActionBeanContext's setRequest/setResponse methods are called (by
DefaultActionBeanContextFactory). This will also retrieve and set a reference
to the user's WikiSession
+- After the ActionBean is resolved by Stripes, the JSPWiki WikiInterceptor
fires and stashes the WikiActionBean into the HTTP request's ACTIONBEAN
attribute. It also stashes the WikiContext (which will either be the
WikiActionBean or a fake WikiContext), WikiEngine and WikiSession. What this
means, in particular, is that JSP EL syntax can be used to access the
"wikiActionBean," "wikiContext," "wikiEngine," and "wikiSession" attributes.
-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:
+- If a Stripes event handler method is being called, the JSPWiki
WikiInterceptor fires again just after the event handler is identified, and
checks for proper access by the user. Access is determined by checking if the
user possesses the required permission (null means "allowed"). If not, a
RedirectResolution is returned that directs the user to the login page and
appends all request parameters. (Note: we should make it check for
authentication; if the user is already logged in, it should redirect to a
"forbidden" page.
- @DefaultHandler
- @HandlesEvent("view")
- @EventPermission(permissionClass=PagePermission.class,
target="${page.qualifiedName}", actions=PagePermission.VIEW_ACTION)
- public Resolution view() { ... }
+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. And the
WikiSession, WikiEngine, WikiContext and WikiActionBean are all available as
JSP EL variables.
-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?
+2) Stripes automatic binding of ActionBean via POST/GET to /dispatcher,
/action/* or *.action URLs. This method is used, in particular, by generated
Stripes form elements. It is rare that a user would actually specify one of
these URLs directly.
-i18n
-----
-Switching to Stripes for URL building (via URLBuilder) causes UTF-8 strings to
be created by the getURL methods:
+As with the previous method, the WikiActionBean is looked up by Stripes'
configured ActionResolver. The same guarantees apply: after resolution and
instantiation, the WikiActionBean will have a non-null, valid
WikiActionBeanContext, and that the WikiActionBeanContext will return non-null
results for
getResponse/getRequest/getServletContext/getWikiEngine/getWikiSession. The four
variables named above (wikiActionBean, wikiContext, wikiEngine, wikiSession)
are injected as request attributes.
-So:
-<a class="wikipage"
href="/Wiki.jsp?page=%C4itiSy%F6%D6ljy%E4">ÃitiSyöÃljyä</a>
+These two techniques are the preferred ways to create WikiActionBeans. There
are three other, less preferred, ways:
-becomes:
-<a class="wikipage"
href="/Wiki.jsp?page=%C3%84itiSy%C3%B6%C3%96ljy%C3%A4">ÃitiSyöÃljyä</a>
+3) WikiEngine.createContext( HttpServletRequest, String).
+Although the <useActionBean> and URl-binding methods are now the preferred way
to create WikiActionBeans (and their WikiContext subclasses), for backwards
compatibility reasons the WikiEngine.createContext() has been retrofitted to
create WikiContexts in the proper way. Note that for backwards compatibility
reasons, createContext() ONLY creates objects of type WikiContext rather than
the superclass type WikiActionBean. (It would have been too much work to change
the return type.)
-Migration to Stripes tags:
+WikiEngine.createContext honors the same contract as the previous techniques.
If null is supplied for the request parameter, a mock objects is synthesized.
Thus, when the createContext() method is used, the resulting WikiContext 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 getServletContext/getWikiEngine/getRequest/getResponse methods.
-stripes:form. must change accept-charset to acceptcharset
+Note that the createContext() technique differs in one important respect from
the <useActionBean> or Stripes URL binding techniques. Although it will
correctly identity the page requested by the user (by inspecting request
parameters), it will not do anything special if the page is a "special page."
If special page resolution and redirection is required, use the
<stripes:useActionBean> JSP tag instead.
-WikiTagBase extents StripesTagSupport in 3.0, not TagSupport. That means we
needed to create a few methods that are in TagSupport but aren't in
StripesTagSupport. Easily done...
+4)
WikiActionBeanFactory.newActionBean(HttpServletRequest,HttpServletResponse,Class<?
extends WikiActionBean>).
-Also, the method TagSupport.findAncestorWithClass which is used by TabTag
needs to be replaced by StripesTagSupport.getParentTag (without need for
classcast).
+This method performs a similar role to createContext(), in the sense that it
will instantiate an arbitrary WikiActionBean class and, in the case of
WikiContext subclasses, bind a WikiPage to it. As with the previous
techniques, it will instantiate a new WikiActionBean and associate it with a
new, synthetic, WikiActionBeanContext. If nulls are supplied for the request or
response parameters, mock objects are synthesized so that the contract is
honored.
+5) WikiActionBeanFactory.newViewActionBean(
HttpServletRequest,HttpServletResponse,WikiPage).
-Thoughts on URLConstructor
---------------------------
-http://tuckey.org/urlrewrite/manual/3.0/
+This methods instantiates a ViewActionBean and associates a
WikiActionBeanContext with the bean. The WikiActionBeanContext's setWikiEngine
and setServletContext methods are called after instantiation. If request or
response objects are supplied, it is associated with the WikiActionContext. If
not, mock objects are synthesized so that the contract is honored.
-Looks like we could rewrite everything!
+In addition to these five techniques, callers can create new WikiActionBeans
via the zero-arg constructor [WikiContext context = new ViewActionBean()];
however, callers must also honor the contract for returning non-null
WikiEngine, WikiActionBeanContex and request/response references. It's much
easier, instead, to call the factory method
WikiActionBeanFactory.newActionBean( WikiPage page), which does it for you.
-For inbound requests: if UrlRewrite is the first servlet filter it will
translate correctly coming in. Thus: /wiki/Page1 might forward to
/wiki/Wiki.jsp?page=Page1.
-
-For outbound responses: UrlRewrite needs to be the last thing that manipulates
the URL. For outbound URLs, you can generate a useful URL by calling
HttpServletResponse.encodeURL(String), where the parameter is the URL you want
to re-write.
+WikiActionBean Security
+-----------------------
+In 2.4, security permissions were added to WikiContexts. Each WikiContext
could specify what Permission a user needed to access that context by causing
the method requiredPermission() to return a value. This worked well, although
it required each WikiContext type ("view","edit" etc.) to figure out a way to
express the Permission through code. This, in part, was what let to the
disaster that is the Command class.
- --> Note: this means WikiServlet goes away (the destroy logic goes to
WikiServletFilter for now)
+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:
-Making things a little tricker: Stripes Resolutions also generate their own
URLS. This is done by creating a new RedirectResolution(WikiActionBean), where
the WikiActionBean is the "url" you want to redirect to. Add parameters as
necessary.
+ @DefaultHandler
+ @HandlesEvent("view")
+ @EventPermission(permissionClass=PagePermission.class,
target="${page.qualifiedName}", actions=PagePermission.VIEW_ACTION)
+ public Resolution view() { ... }
-To tie all of this together:
+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?
-Some classes currently call the URLConstructor directly. Mostly, this is
WikiContext and WikiEngine (about 22 references in the JSPWiki core classes,
plus 2 in the JSPs). However, most classes get their URLs by calling
WikiContext.getViewURL(), getRedirectURL(), and getURL()/getURL() -- 73
references within the core, and 23 references in the templates. These probably
should not be changed for compatibility's sake. However, we could easily cause
these WikiContext/WikiEngine references to URLContructor instead to use
Resolution.getURL + response.encodeURL().
-WIKICONTEXT OVERHAUL
---------------------
+WIKICONTEXT
+-----------
In JSPWiki versions prior to 3.0, WikiContext objects were created by calling
a public constructor, followed by a call to setRequestContext(String). In 3.0,
however, WikiContext becomes an interface [abtract class?] so contructors don't
work. Instead, callers wishing to create WikiContexts should instead use the
factory method WikiActionBeanFactory.newActionBean(request,response,beanClass).
As an alternative, callers may also call
WikiEngine.createContext(request,String).
FORWARDING METHODS
-getContentTemplate(): to super
-getJSP(): to super -- do we calculate it? put it in as an
annotation?
getEngine(): to super
getRequestContext(): to super
getVariable(String): to super
@@ -131,10 +272,10 @@
setPage()
findContext() -- no change
hasAdminPermissions()
-getLocale(m_context) forwards to m_context.getContext().getLocale();
+getLocale(m_context) -- forwards to WikiActionBeanContext.getLocale();
D hasAccess(HttpServletResponse) -- used in MANY JSPs. Refactored to look up
the permission info for the method that contains @DefaultHander annotation.
D hasAccess(HttpServletResponse,boolean) -- referenced only by other
hasAccess().
-setRequestContext() -- refactor to set the action bean event (if request
context matches, otherwise throw error; NONE always matches)
+setRequestContext() -- now delegates to set the action bean event (if request
context matches, otherwise throw error; NONE always matches)
clone() -- needs refactoring
BACKWARDS INCOMPATIBILITIES
@@ -146,22 +287,21 @@
getTarget()
getURLPattern()
getCommand()
-requiredPermission() -- only used in tests and WikiContext itself. Ok to kill
+requiredPermission() -- only used in tests and WikiContext itself. Ok to kill.
Replaced by WikiInterceptor in combination with event-level annotations
targetedCommand()
+getContentTemplate(): only used by ContentTag and Command/CommandResolver tests
+getJSP(): only used by ContentTag and Command/CommandResolver tests
setDefaultTemplate() [Protected]
findCommand() [Protected]
updateCommand() [Protected]
WIKIENGINE
----------
-WikiEngine.createContext(req, String) changes its internal behavior. It
delegates to m_engine.getWikiActionBeanFactory().newActionBean(Class<? extends
ActionBean). The String request context must resolve to a WikiContext subclass
rather than a more general WikiActionBean; if not, an IllegalArgumentException
is thrown.
-
-WikiEngine.getURL() should be banned! (What should it do instead....?)
-
DEPRECATIONS
getURLContructor() -- should use URLBuilder instead, with request awareness
getViewURL() -- refactored; should use URLBuilder instead, with request
awareness
-createContext() -- refactored to use WikiActionBeanFactory instead
+createContext() -- changes its internal behavior. It delegates to
m_engine.getWikiActionBeanFactory().newActionBean(Class<? extends ActionBean).
The String request context must resolve to a WikiContext subclass rather than a
more general WikiActionBean; if not, an IllegalArgumentException is thrown.
+getSpecialPageReference(). Used exactly once, in NewBlogEntry.jsp.
BACKWARDS INCOMPATIBILITIES
getRedirectURL() -- only used on once place: Wiki.jsp
@@ -180,11 +320,14 @@
Workflow.jsp
templates/default/AJAXSearch.jsp
-URLCONSTRUCTOR -- keep package but deprecate all of it! UrlContructors suck
because they have no visibility to the user's context. Stripes URLBuilder is
much better; that is what WikiActionBeanContext uses.
+URLCONSTRUCTOR
--------------
+The package remains but is deprecated. UrlContructors suck because they have
no visibility to the user's context. Stripes URLBuilder is much better; that is
what WikiActionBeanContext uses.
+
DEPRECATIONS
getForwardPage() -- used only by WikiServlet; refactor to delegate to
WikiActionBeanFactory
parsePage() -- used only by CommandResolver & URLContructor implementations;
refactor to delegate to WikiActionBeanFactory
+
Deprecated all URLConstructor implementations.
@@ -207,132 +350,48 @@
UrlBuilder urlBuilder = new UrlBuilder( groupUrl, true );
urlBuilder.addParameter("group", name);
String url = urlBuilder.toString();
-
- // Make re-written URL
- String rewriteUrl = context.getContext().getResponse().encodeURL(
url );
-
-
---> Note: this means we need to replace WikiEngine.getURL() calls with
equivalent calls to UrlBuilder + response.encodeUrl()
-
-WikiEngine.getURL goes away completely. Now, we need to get the
ActionBeanContext in order to generate an URL.
-
-
-ContentTemplates, JSPs, URLPatterns and RequestContexts
--------------------------------------------------------
-In 2.4 we welded ContentTemplates, JSPs and RequestContexts together in the
Command class. This helped unify some things, but it really doesn't fit in with
Stripes all that well. Frankly, specifying a content template is really in the
domain of JSP markup, and shouldn't be in classes. The URLPatterns are there
because we need them for the URLConstructor. But if we delegate URL
construction to Stripes and UrlRewrite, then we don't need this anymore.
RequestContexts are still useful because we need to look up ActionBeans (e.g.,
WikiContexts) that way. We should still allow them, but deprecate them.
-
-General behaviors need to change in the JSP layer so that instead of looking
up a URL and then calling redirect directly, we need instead to obtain
RedirectResolutions.
-
-Stashing variables in PageContexts
-----------------------------------
-WikiTagBase chokes hard when it can't find a WikiContext associated with the
the PageContext. That's because there's an expectation that the top-level JSP
will stash the right context. In the new world WikiContexts are supplanted by
ActionBeans. Do the page-specific tags need guaranteed access to a WikiContext?
Hmm.... how can we stick one in there upstream? Do we name specific beans
PAGE_BEAN, GROUP_BEAN, etc. or do push/pop operations
-
-Contract ought to be: top-level JSP *guarantees* that it will inject a
WikiActionBean, with a well-known name ACTIONBEAN ("wikiActionBean"), into
request scope. WikiTagBase should first look for the well-known ActionBean,
then iterate through the stored attributes and grab the first value it finds of
type ActionBean. If an ActionBean can't be found, throw a WikiException. (Like
what we do now.)
-
-Thus: by convention, top-level JSPs MUST add a tag similar to this to the top
of their pages if they want the bean recognized later by WikiTagBase:
-
-<stripes:useActionBean beanclass="com.ecyrd.jspwiki.action.____ActionBean"/>
-
-The first JSP to to use the useActionBean class will, by definition, cause the
ACTIONBEAN request attribute to be set with this name binding. WikiTagBase's
m_actionBean will obtain this value.
-
-Note: redefining m_context as m_actionBean (with type change to
WikiActionBean) makes 32 out of 70 JSP tags fail to compile because they expect
a getPage() method. We will need to supply guidance on how to migrate tags.
-In JSPs, the fact that the WikiActionBean for the page is bound as
'wikiActionBean' means that JSTL markup can access this parameter directly. It
also means that we can *probably* get rid of the WikiContext.getContext()
static method. In fact, we probably should. But for now, it's best to leave it
but redefine the return type so that it's a WikiActionBean. That will break a
few things.
-
-Dead Code
----------
-WikiEngine.getRedirectURL(). Not used anywhere in the new code, and only once
in the old Wiki.jsp. Eliminated.
-
-WikiEngine.createContext(). Better to use WikiActionBeanFactory.find...
-
-WikiEngine.getSpecialPageReference(). Used exactly once, in NewBlogEntry.jsp.
Eliminated.
-
-WikiTagBase now guarantees that the protected field m_page will be set if it's
a WikiContext This eliminates lots of classcasting.
-
-Things I haven't solved yet
----------------------------
-Stopwatch from Wiki.jsp
-WatchDog from Wiki.jsp
-
-API Changes
------------
+VariableManager
+---------------
VariableManager.getValue method sigs widened to WikiActionBean (from
WikiContext to WikiActionBean)
-ContentTag's default content page is Beanclass name - "ActionBean" +
"Content.jsp"
-
-WikiSession/ActionBeanContext
------------------------------
-Stripes ActionBeanContext wraps the request/response objects and provides
information about the servlet context. It is created anew for each request, I
think. So it's not suitable for "merging" with WikiSession.
-
-WikiContext getLocale(). Not used in JSPs or core code. Because Stripes takes
care of a lot of this, it's not needed.
-
-WikiContext hasAccess(). Really, this should be handled by the stripes
interceptor/controller. So these methods should absolutely be eliminated.
-
-
-
-
-WikiActionBean Contract
------------------------
-WikiActionBeans are the core action class in JSPWiki 3.0. All WikiActionBeans
are expected to adhere to the following contract:
-- must have a zero-argument constructor
-- must set the ActionBeanContext immediately after instantiation (setContext)
-- must set the associated ActionBeanContext's WikiEngine immediately after
instantiation (setWikiEngine)
-
-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 effort, and only requires single line at the top of a
top-level JSP:
-
-<stripes:useActionBean beanclass="com.ecyrd.jspwiki.action.____ActionBean"/>
-
-Technically, the WikiActionBean is looked up by Stripes' configured
ActionResolver (by default, the AnnotatedClassActionResolver); the bean itself
is instantiated using its zero-argument constructor. Stripes guarantees that
the following things happen after instantiation, as part of its
ActionBeanResolution lifecycle stage:
-- The WikiActionBean's setActionBeanContext() method is called (by
AnnotatedClassActionResolver); this causes a reference to a new
WikiActionBeanContext to be set in the WikiActionBean
-- The WikiActionBeanContext's setServletContext() method is called (by
UseActionBeanTag); this sets an internal reference to the WikiEngine
-- The WikiActionBeanContext's setRequest/setResponse methods are called (by
DefaultActionBeanContextFactory). This will also retrieve and set a reference
to the user's WikiSession
-
-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.
-
-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.
-
-As with the previous method, the WikiActionBean is looked up by Stripes'
configured ActionResolver. The same guarantees apply: after resolution and
instantiation, the WikiActionBean will have a non-null, valid
WikiActionBeanContext, and that the WikiActionBeanContext will return non-null
results for
getResponse/getRequest/getServletContext/getWikiEngine/getWikiSession.
-
-In addition to these activities, in cases 1) and 2), after the
ActionBeanResolution stage completes, JSPWiki's custom WikiInterceptor
executes. It will do two things:
-
-- Stash the resolved WikiActionBean into the HTTP request's ACTIONBEAN
attribute (see above)
+WikiTagBase
+-----------
+WikiTagBase changes slightly to support Stripes. Instead of extending import
javax.servlet.jsp.tagext.TagSupport, it now extends StripesTagSupport. However,
StripesTagSupport does not supply the methods setId/GetId. So, we've had to
implement these. Also, the method TagSupport.findAncestorWithClass which is
used by TabTag needs to be replaced by StripesTagSupport.getParentTag (without
need for classcast).
-- Check for proper access by calling the the bean's requiredPermission()
method and checking that the user has that permission (null means "allowed").
If not, a RedirectResolution is returned that directs the user to the login
page and appends all request parameters. (Note: we should make it check for
authentication; if the user is already logged in, it should redirect to a
"forbidden" page.
-These two techniques are the preferred ways to create WikiActionBeans. There
are two other, less preferred, ways:
+TESTING NOTES
+=============
-3)
WikiActionBeanFactory.newActionBean(HttpServletRequest,HttpServletResponse,Class<?
extends WikiActionBean>).
+Eclipse Tools Notes
+-------------------
+TestEngine: Because of its use of Stripes mock objects, TestEngine needs to be
able to find the various implementations provided in JSPWiki. Therefore, it is
extremely sensitive to changes in the build path. In particular, the mock
servlet filter used by TestEngine hard-wires in the relative location build for
finding ActionBeans. This is the directory (relative to the project root) that
the Ant build scripts use for placing generated Java class files. The Eclipse
project configuration must configure itself the same way. To run unit tests in
Eclipse, the build directory absolutely must place generated class files in
this directory, rather than the Eclipse default of classes. If unit tests do
not run in Eclipse for some reason, this is the likeliest culprit.
+Use JVM args -Xmx1024m
-In this case, JSPWiki does things a little differently than how Stripes does
it, but the result is the same. Like Stripes, it will instantiate a new
WikiActionBean and associate it with a new WikiActionBeanContext.
+Eclipse... Software Update
+New Remote Site:
+Name: Findbugs
+URL: http://findbugs.cs.umd.edu/eclipse
-4) WikiActionBeanFactory.newActionBean( HttpServletRequest request, WikiPage
page) and
-WikiActionBeanFactory.newActionBean( WikiPage page).
+Name: CheckStyle Eclipse Plug-in
+URL: http://eclipse-cs.sourceforge.net/update
-Both of these methods instantiate ViewActionBeans and associate a
WikiActionContext with the bean. The WikiActionContext's setWikiEngine and
setServletContext methods are called after instantiation. If an
HttpServletRequest was supplied, it is associated with the WikiActionContext.
-Thus, when the createContext() methods are used, the resulting ViewActionBean
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 getServletContext/getWikiEngine methods. Its getRequest()
method may or may not be null.
+Bugs Bugs Bugs
+==============
+i18n
+----
+Switching to Stripes for URL building (via URLBuilder) causes UTF-8 strings to
be created by the getURL methods:
-WikiTagBase
------------
-WikiTagBase changes slightly to support Stripes. Instead of extending import
javax.servlet.jsp.tagext.TagSupport, it now extends StripesTagSupport. However,
StripesTagSupport does not supply the methods setId/GetId. So, we've had to
implement these.
+So:
+<a class="wikipage"
href="/Wiki.jsp?page=%C4itiSy%F6%D6ljy%E4">ÃitiSyöÃljyä</a>
-WikiActionBeanFactory
----------------------
-newActionBean() This method performs a similar role to the
<stripes:useActionBean> tag, in the sense that it will instantiate an
arbitrary WikiActionBean class and, in the case of WikiContext subclasses, bind
a WikiPage to it. However, it lacks some of the capabilities the JSP tag
possesses. For example, although this method will correctly identity the page
requested by the user (by inspecting request parameters), it will not do
anything special if the page is a "special page." If special page resolution
and redirection is required, use the <stripes:useActionBean> JSP tag
instead.
+becomes:
+<a class="wikipage"
href="/Wiki.jsp?page=%C3%84itiSy%C3%B6%C3%96ljy%C3%A4">ÃitiSyöÃljyä</a>
-Eclipse Tools Notes
--------------------
-TestEngine: Because of its use of Stripes mock objects, TestEngine needs to be
able to find the various implementations provided in JSPWiki. Therefore, it is
extremely sensitive to changes in the build path. In particular, the mock
servlet filter used by TestEngine hard-wires in the relative location build for
finding ActionBeans. This is the directory (relative to the project root) that
the Ant build scripts use for placing generated Java class files. The Eclipse
project configuration must configure itself the same way. To run unit tests in
Eclipse, the build directory absolutely must place generated class files in
this directory, rather than the Eclipse default of classes. If unit tests do
not run in Eclipse for some reason, this is the likeliest culprit.
-Use JVM args -Xmx1024m
-URL Rewriting
--------------
-http://tuckey.org/urlrewrite/manual/3.0/
-Bugs Bugs Bugs
---------------
JSPWikiMarkupParserTest.testAttachmentLink
Expected
@@ -379,26 +438,6 @@
----------------
All of the non-top-level JSPs that shouldn't be directly instantiated are
moved to /WEB-INF/jsp/layout.
-Some changes:
-JSPs don't need this any more: <fmt:setBundle basename="templates.default"/>
-...because we set a context parameter in web.xml.
-
-Scriptlet code in JSPs that needs to obtain a reference to the WikiEngine can
simply use ${wikiEngine}.
-
-Good practice: whenever useActionBean is used in a JSP, author should always
set the 'var' attribute so that downstream JSPs can use the variables.
-
-WikiInterceptor will attempt to set the current WikiActionBean and WikiPage
into page scope. These are available as ${wikiPage}. It will also set
${wikiEngine} and ${wikiSession}. These are set in request scope.
-
-Migration: this means...
-<%
- WikiContext c = WikiContext.findContext(pageContext);
- WikiPage wikipage = c.getPage();
-%>
-...can simply be replaced by ${wikiPage}.
-
-
-
-BUG: LinkTag didn't always init its m_containedParameters map. (So, I fixed
it...)
2.6 commonheader.jsp
'JsonUrl' : '<%= WikiContext.findContext(pageContext).getURL(
WikiContext.NONE, "JSON-RPC" ) %>'
@@ -420,15 +459,6 @@
This is replaced:
<wiki:Content/>
by
-
-
-Scriptlet code (e.g., PageTab.jsp)
-
- WikiContext c = WikiContext.findContext( pageContext );
-
-Replaced by
-
- WikiContext c = (WikiContext)WikiInterceptor.findActionBean();
Wiki:Tab needs to be able to evaluate attribute contents... now it doesn't...
@@ -436,13 +466,12 @@
Things that don't work
----------------------
RSSGenerator, probably...
-WikiJSPFilter should not have the lookup bean method...
-The Stripes version has a qualfied name method in WikiPage, Group etc. Did
these go away in 2.6?
FeedDiscoveryTag probably needs a total re-compare.
Groups looks like it generates URLs in a funny way...
-ContentTag looks quite screwed up! (shouldn't append the *Content.jsp suffix,
should it?)
+
FeedDiscoveryTeg generates URLs in a funny way...
+
Not sure about ResolutionException and RedirectException... committed them
anyway.
Selenium tests are temporarily borked because we use the old JSPs.