Java Development with Ant: Struts
This application uses Jakarta Struts for its search and search results
display. This is a trivial Struts implementation as there is only one
form bean and one true action. While this is a simplistic example of
Struts usage, it has some very powerful features and examples of Struts best-practices:
- Uses a base action
rather than extending from the Struts Action class directly.
- Links pages together using a custom SuccessAction.
This allows easier modification later without the need to touch JSP
pages to adjust links.
- Leverages XDoclet to generate struts-config.xml
and the Validator framework validation.xml using metadata tagged in the form bean.
- Uses a custom tag
to display field labels, with error hilighting and required field status
display.
Generating struts-config.xml
XDoclet is used to generate struts-config.xml. Actually the only part
that is dynamically generated is the form bean definitions section from the
form bean source code. The action mappings are stored in a merge point
file called struts-actions.xml.
XDoclet has the capability to generate action mappings, but this project
does not showcase this. Read the
FAQto to see why.
Making validation easy
This project uses a feature very new to XDoclet. In fact, I wrote this
and its my contribution back to XDoclet (but file bug reports with the XDoclet
project). Hand-maintaining validation.xml is painful and very error-prone.
When using the Validator framework with Struts, there is now an easier
way. Tag form bean code with the validations for fields by marking
the setters with @struts.validator tags and use the <strutsvalidationxml>
subtask and the validation.xml file will be automatically generated for you.
For example, the query field on SearchForm (see code below) is required
and is tagged with @struts.validator type="required". That one tag
is all that is needed to make a field required. There are several other
options for changing the error message key, using Validator variables, and
controlling Validator settings precisely. Refer to the XDoclet project
documentation for details on these features.
Struts form/resource generator
Hidden in the tools directory is a custom tool which generates a starter JSP
page and field labels in properties file format for easy cut and paste into
the main application code base. The complete code for SearchForm is:
package org.example.antbook.struts;
import org.apache.struts.validator.ValidatorForm;
/**
* Search query entry form.
*
* @struts.form name="SearchForm"
*/
public class SearchForm extends ValidatorForm {
private String query;
/**
* Sets the query attribute of the SearchForm object
*
* @struts.validator type="required" msgkey="query.required"
*/
public void setQuery(String query) {
this.query = query;
}
public String getQuery() {
return query;
}
}
To run the strutsgen tool, simply run the build file in the tools/strutsgen
directory and specify the form bean to process using the form.name Ant property.
Here is an example of it generating a JSP and properties file piece
for the SearchForm:
% ant -Dform.name=SearchForm
Buildfile: build.xml
clean:
[delete] Deleting directory /Users/erik/dev/scorpion/Presentations/example/tools/strutsgen/build
init:
[mkdir] Created dir: /Users/erik/dev/scorpion/Presentations/example/tools/strutsgen/build
compile:
[javac] Compiling 1 source file to /Users/erik/dev/scorpion/Presentations/example/tools/strutsgen/build
gen:
[xdoclet] Running <template/>
[xdoclet] Generating output for 'org.example.antbook.struts.SearchForm' using template file 'file:/Users/erik/dev/scorpion/Presentations/example/tools/strutsgen/src/FormKeys.xdt'.
[xdoclet] Running <template/>
[xdoclet] Generating output for 'org.example.antbook.struts.SearchForm' using template file 'file:/Users/erik/dev/scorpion/Presentations/example/tools/strutsgen/src/StrutsForm_jsp.xdt'.
default:
BUILD SUCCESSFUL
Total time: 7 seconds
In the build directory of the strutsgen tool, two files are created. One
is a JSP file and the other is a properties file. The properties file
from the above generation is:
SearchForm.query=Query
When a new form is added to the system, these steps are taken:
- Create the ValidatorForm subclassed form bean, tagged with @struts.form
name="<form name>" (at class level) and any @struts.validator
needed to validate input fields (at setter method level).
- Run strutsgen, with form.name set to be the Java class name (which should,
for convention reasons, be the same as the form name tagged).
- Copy the generated JSP to the desired location (under the root web directory
for the JavaDevWithAnt project).
- Cut and paste the properties file piece generated into the main ApplicationResources.properties
file.
- Run the main build and ensure that the XDoclet-generated struts-config.xml
and validation.xml files have the new form definition and field validations,
respectively.
In order to adjust how new JSP's are generated to suit your project conventions/preferences
simply edit src/StrutsForm_jsp.xdt. Most of the template is pure JSP
code, but there is sprinkling of XDoclet to generate the field labels and
input fields. The relevant pieces are shown here:
<XDtTagDef:tagDef namespace="Struts" handler="org.example.antbook.xdoclet.FormTagsHandler"/>
some template JSP code not shown here
<XDtStruts:forAllFields>
<tr>
<th><bean:message key="<XDtClass:classTagValue tagName="struts.form" paramName="name"/>.<XDtStruts:fieldName/>"/></th>
<td><html:text property="<XDtStruts:fieldName/>"/></td>
</tr>
</XDtStruts:forAllFields>
A custom XDoclet tag handler was written to pull all valid form fields from
the form bean, iterate over them, and to provide an attractive name to the
field label in the properties file. It should not be necessary to adjust
the properties file template, however it is available in src/FormKeys.xdt.