I was wondering if it's mandatory to specify on a FormTag "name" and
"type" parameters since in most cases with Struts forms "action" value
is an ActionMapping path that already contains all needed information
from "action.xml".
I suggest adding to the FormTag a "path" (i.e. <struts:form
path="foo.do"/>) "parameter that if present overrides or compliments
"action", "type" and/or "name". Other solution is to define a new tag
such as FormPathTag (i.e. <struts:pathform>) derived from current
FormTag. In any case this will allow in a true MVC fashion to keep most
technical non design information such as full bean class names and id's
in a single place and not to replicate them through jsp pages. Also
this makes FormTag extremely easy to explain and use with a single param
such as:
<struts:form path="foo.do"/>
Following is proposed patch that for brevity assumes extending FormTag
and that "path" param overrides "action", "type" and "name" params if
present. Alternatively it's easy to check if any of above params is
present and if not override it with values form ActionMapping.
Corresponding TLD entry should redefine "name" and "type" params as
optional and an optional "path" param.
Btw, are efficiency benefits so considerable with most Tag classes being
defined as "final" so it's impossible to extend them?
public class FormPathTag extends FormTag {
/**
* An URL which path should match according to ActionServlet rules
* action mapping name from action.xml thus eliminating the need to
specify
* form tag bean name and type.
* Supersedes action, type and name params if specified.
*/
private String path = null;
public String getPath() {
return (this.path);
}
public void setPath(String path) {
this.path = path;
}
/** Process path param if present and use
* params from corresponding ActionMapping
*/
public int doStartTag() throws JspException {
if ((path == null) || (path.length () < 1)) return;
setAction (mapping); // use is as form action
// Find ActionMapping pointed by the path
ActionMappings actmaps = (ActionMappings)
pageContext.getAttribute
(Action.MAPPINGS_KEY, PageContext.APPLICATION_SCOPE);
ActionMapping actmap = actmaps.findMapping (getMappingPath
(path));
if (actmap == null)
throw new JspException
(messages.getMessage("common.io",
"FormTag: No ActionMapping found for form tag path
value: " + path));
// Override FormTag params with bean type and name extracted
from mapping
setType (actmap.getFormClass ());
setName (actmap.getFormAttribute ());
super.doStartTag();
}
/**
* Identify and return the action path component (from the path URI)
that
* we will use to select an ActionMapping. If no such
* path can be identified, return <code>null</code>.
*/
protected static String getMappingPath (String uri)
{
String path = new String (uri); // make a copy
// For extension matching, we want to strip the extension (if
any)
int slash = path.lastIndexOf ("/");
int period = path.lastIndexOf (".");
if ((period >= 0) && (period > slash))
path = path.substring (0, period);
// Add a leading "/" if missing
if (!path.startsWith ("/"))
path = "/" + path;
return (path);
}
public void release() {
super.release();
path = null;
}
}
|