How to Build an Action Form

This is a simple example of a login form to illustrate how Struts Action Framework makes dealing with forms much less painful than using straight HTML and standard JSP facilities. Consider the following page (based on the Struts MailReader example) named logon.jsp:


<%@ page language="java" %>
<%@ taglib  uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<html:html>
<head>
<title>
    <bean:message key="logon.title"/>
</title>
</head>

<body bgcolor="white">

<html:errors/>

<html:form action="/logon" focus="username">
<table border="0" width="100%">
    <tr>
        <th class="right">
            <bean:message key="prompt.username"/>
        </th>
        <td class="left">
            <html:text  property="username" size="16"/>
        </td>
    </tr>
    <tr>
        <th class="right">
            <bean:message key="prompt.password"/>
        </th>
        <td class="left">
            <html:password property="password" size="16"/>
        </td>
    </tr>
    <tr>
        <td class="right">
            <html:submit>
                <bean:message key="button.submit"/>
            </html:submit>
        </td>
        <td class="right">
            <html:reset>
                <bean:message key="button.reset"/>
            </html:reset>
        </td>
    </tr>
</table>

</html:form>
</body>
</html:html>

The following items illustrate the key features of form handling, based on this example:

  • The taglib directive tells the JSP page compiler where to find the tag library descriptor for the Struts JSP tags. In this case, we are using bean as the prefix that identifies tags from the struts-bean library, and "html" as the prefix that identifies tags from the struts-html library. Any desired prefix can be used.
  • This page uses several occurrences of the message tag to look up internationalized message strings from a MessageResources object containing all the resources for this application. For this page to work, the following message keys must be defined in these resources:
    • logon.title - Title of the logon page
    • prompt.username - A "Username:" prompt string
    • prompt.password - A "Password:" prompt string
    • button.submit - "Submit" for the button label
    • button.reset - "Reset" for the button label
    When the user logs on, the application can store a Locale object in the user's session. This Locale will be used to select messages in the appropriate language. This makes it easy to implement giving the user an option to switch languages -- simply change the stored Locale object, and all messages are switched automatically.
  • The errors tag displays any error messages that have been stored by a business logic component, or nothing if no errors have been stored. This tag will be described further below.
  • The form tag renders an HTML <form> element, based on the specified attributes. It also associates all of the fields within this form with a ActionForm bean [org.apache.struts.action.ActionForm]. The tag looks up the /logon action mapping in the Struts configuration. The logon mapping tells the tag that the form bean is stored in the session context under the key logonForm. The developer provides the Java implementation of the ActionForm bean, subclassing the Struts class ActionForm (see Building Controller components). This bean is used to provide initial values for all of the input fields that have names matching the property names of the bean. If an appropriate bean is not found, a new one will be created automatically, using the Java class name specified through the action mapping.
  • The form bean can also be specified in the tag by providing name and type attributes. But most often, everything is specified in the Struts Configuration File.
  • The text tag renders an HTML <input> element of type "text". In this case, the number of character positions to occupy on the browser's screen has been specified as well. When this page is executed, the current value of the username property of the corresponding bean (that is, the value returned by getUsername ).
  • The password tag is used similarly. The difference is that the browser will echo asterisk characters, instead of the input value, as the user types their password.
  • The submit and reset tags generate the corresponding buttons at the bottom of the form. The text labels for each button are created using message tags, as with the prompts, so that these values are internationalized.

Transferring Data

To transfer data between ActionForms and business objects, many developers use the Commons BeanUtil methods. To transfer data from an ActionForm to a business object, you can use a statement like:

            PropertyUtils.copyProperties(actionForm, businessObject);

To transfer data from a business object to an ActionForm, you can reverse the parameters

            PropertyUtils.copyProperties(businessObject, actionForm);

For more about using this technique, see the Commons BeanUtils documentation, and the Struts MailReader example application.

Aside from BeanUtils, there are other tools available that make it easier to use business objects and ActionForms together. For more about POJO ActionForms, see the FormDef extension and the Struts Live toolkit.

Multipart Forms

Handling multipart forms is also easy. Obviously when you create a multipart form you're creating a form that has at least one input of type "file". The first step to creating a multipart form is to utilize the struts-html taglib to create the presentation page:

<%@page language="java">
<%@taglib
    uri="/WEB-INF/struts-html.tld"
   prefix="html">

<html:form action="uploadAction.do" enctype="multipart/form-data">

    Please Input Text: <html:text property="myText">
    Please Input The File You Wish to Upload: <html:file property="myFile">

   <html:submit />

</html:form>

The next step is to create your ActionForm bean:


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;

public class UploadForm extends ActionForm {

    protected String myText;
    protected FormFile myFile;

    public void setMyText(String text) {
        myText = text;
    }

    public String getMyText() {
        return myText;
    }

    public void setMyFile(FormFile file) {
        myFile = file;
    }

    public FormFile getMyFile() {
        return myFile;
    }

}

Look at the Javadocs for FormFile to see the methods it exposes to manipulate files in file uploading. Also look at the Javadocs for ActionServlet and ActionMapping for the various parameters you can specify to change how files are uploaded. Basically in your execute method in your action class you would call ((UploadForm) form).getMyFile() to retrieve the FormFile and do what you want with it.