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:

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:

  1. 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).
  2. 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).
  3. Copy the generated JSP to the desired location (under the root web directory for the JavaDevWithAnt project).
  4. Cut and paste the properties file piece generated into the main ApplicationResources.properties file.
  5. 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.