Last year I wrote an article about Struts 1.0. With the release of Struts 1.1 beta, it is time for an update to that article. First we will look at how to change last year's simple logon application to run correctly in Struts 1.1. Then we will look at one of the interesting new additions to Struts, the validator framework, and show how it can simplify our application.
The installation of Struts has not changed much except that there are more files to install. The struts.jar file has had many of the common classes pulled out and placed into separate jar files. There are now thirteen jar files to place in your applications lib directory. Also, the TLD files have been changed a little bit. The struts.tld file has been eliminated and its functionality moved into other TLD files. There are two additional TLD files to add to your WEB-INF directory. You need to update the web.xml file for the changes to the tag library descriptors but no other changes are required.
Our Struts 1.0 application won't work as it was written. At the very minimum, we need to make changes to our
two JSP files because we no longer have the struts.tld file. The change is simple. We first remove the taglb directive
that contains struts.tld and then we change struts:message to bean:message
everywhere it appears.
At this point we can run our application but it still contains some deprecated code. The LoginAction class
needs to be changed because of deprecated code. First, the key method of our Action class, perform()
has been deprecated. The reason for doing this was because the perform()
could only throw IOException and ServletException and it was realized that Action classes should be able to throw
any Exception required by the programmer. Since it was desired that code still be backward compatible, a new method
was added in place the perform() method. The new method is execute().
Here is the method signature:
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws java.lang.Exception |
import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.struts.*; public class LoginAction extends Action { public LoginAction() {} public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws java.lang.Exception { LoginBean lb = new LoginBean(); request.setAttribute("LoginBean", lb); lb.setParameters(request); ActionErrors ae = lb.validate(); request.setAttribute(Globals.ERROR_KEY, ae); if (ae == null || ae.size() == 0) { return mapping.findForward("valid"); } else { return mapping.findForward("invalid"); } } } |
Most ActionForm classes (and our example one is no exception) are fairly simple, containing little more than
field level validations. In our example, we are simply testing to insure that the user actually filled in the fields.
Imagine a large application with dozens of forms and you get the idea that you can wind up maintaining a large
number of extremely simple and similar classes.
The solution is provided in Struts 1.1 with the addition of the ValidatorForm and DynaValidatorForm
classes. Using the validator framework is actually very simple to do and eliminates needing to code ActionForm
classes. To set up the validator framework you need to do two things. First, copy the file validator-rules.xml
from the Struts installation files to the WEB-INF directory of your application. Second, update the struts-config.xml
with the plug in information required for the ValidatorPlugIn class. The required element looks like this:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/> </plug-in> |
< !DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> |
We use our validation.xml file to tell Struts which rules to run against which fields in our form. Here is the
entry for our form from the validation.xml file:
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/validation_1_1.dtd"> <form-validation> <formset> <form name="login"> <field property="userId" depends="required,minlength"> <arg0 key="label.userId" /> <arg1 name="minlength" key="${var:minlength}" resource="false"/> <var> <var-name>minlength</var-name> <var-value>4</var-value> </var> </field> <field property="passWord" depends="required"> <arg0 key="label.passWord" /> </field> </form> </formset> </form-validation> |
<form name="login"> - identifies the form-bean that this validation is associated with.
<field property="userId" depends="required,minlength"> - identifies the field
from the form and the validation types to apply to that field.
<arg0 key="label.userId" /> - identifies an argument that will be used to replace a place
holder in the error message associated with this field. The argument is a message resource property.
<arg1 name="minlength" key="${var:minlength}" resource="false"/> - this
is also an argument place holder. The difference is that this will use a variable (identied below it) instead of
a message resource entry. Indirection is permitted here, so the variable can be a string pointing to a message
resource entry. Specifying resource=false prevents Struts from looking for "4" in the message resources.
<var> - identifies that a variable is to follow.
<var-name>minlength</var-name> - identifies the name of the variable. Since we identified that
we are using the "minlength" validator, we are required to supply this variable.
<var-value>4</var-value> - the value of the minlength variable. The "minlength" validator requires
that this field must be an int.
Some of the validators provide JavaScript validation that can be included in your JSP page if you wish. If you use JavaScript validation, the form will be validated in the browser and if it fails validation an alert box will appear and the form will not be sent to the browser. To invoke JavaScript validation first add the html:javascript tag to the page specifying the form to be validated. Then add an onsubmit event handler to the html:form tag and you are finished. The finished LoginView.jsp looks like this with the changes highlighted:
<!-- LoginView.jsp --> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <HTML> <HEAD><TITLE><bean:message key="title.login" /></TITLE> <html:javascript formName="login" /> </HEAD> <BODY> <bean:message key="heading.login" /> <html:errors /> <html:form action="/login" onsubmit="return validateLogin(this)" > <p> <bean:message key="label.userId" />: <html:text property="userId" size="10" /> <br> <bean:message key="label.passWord" />: <html:password property="passWord" size="10" /> <br><br> <html:submit> <bean:message key="button.submit" /> </html:submit> </html:form> </BODY> </HTML> |
errors.required={0} is required.<br> errors.minlength={0} cannot be less than {1} characters.<br> |
<form-bean name="login" type="org.apache.struts.validator.DynaValidatorForm" > <form-property name="userId" type="java.lang.String" /> <form-property name="passWord" type="java.lang.String" /> </form-bean> |
Struts 1.1 is still in beta and the documentation is far from complete. Information on running the validators included with Struts is difficult to find. A lot of the code you work with will be trial and error to get it to run correctly. If you need help getting a feature of Struts to work there are quite a few resources listed on the Struts web site, there is the Struts mailing list, and of course the JavaRanch Framework forum.
When will 1.1 become a release? As with all Apache projects it is difficult to say. This version, beta 3, has been very stable in my testing and provides many improved features to make Struts easier to use. There are a few known issues and once those are fixed we can look forward to a release candidate.