You are on page 1of 11

JavaBoutique - Advanced Forms Handling in Struts 1.

http://javaboutique.internet.com/tutorials/strutsform/article.html

Back to Article

Advanced Forms Handling in Struts 1.1


by Keld H. Hansen

Introduction
This article is about the more advanced features Jakarta Struts offers in building HTML forms. If you know how to create forms in plain HTML then the step to building simple forms in Struts with, for example, a couple of input text elds, a checkbox or a radio button is not very complicated. When it comes to the more complex controls like the multi-valued selection list or a variable length list of input elds it gets more challenging. This is especially true when the possible selections are not xed, but taken from some external source like a database instead. I've too often found myself struggling with the syntax and semantics of the HTML-tags when the forms get complex, and if you search the web for advice, you'll soon see that you have to collect information from many sources. In this article I've tried to collect solutions to the most common non-trivial cases. Every case, of course, is not covered here. Remember to also read Struts' own documentation, starting with the documentation for the HTML-tags. You might nd what you need there. At the end of the article is a table with an overview of the solutions. I'm sure you'll nd it useful when coding your Struts applications. Here's a link to a zip le containing all the examples shown in the article.

The controls in a form


Here is a list of the most commonly used input controls: Type 1. Text eld 2. Text area eld 3. Checkbox 4. Radio button Look Values Anything that can be typed in. One line Anything that can be typed in. Several lines. 1 of 2 (yes/no - on/off) 1 of many xed values

1 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

5. Selection list single type

1 of many xed values. Gives you the same functionality as the radio buttons, only the presentation differs. Several of many xed values

6. Selection list multiple type 7. List of checkboxes

Several of many xed values. Gives you the same functionality as the multi selection list, only the presentation differs.

In Struts you dene a control with a tag from Struts' HTML- library. The next table shows how these are mapped to the old, well-known HTML tags: Type 1. Text eld 2. Text area eld 3. Checkbox Struts html-tag
<html:text property="firstname"/> <html:textarea property="address"/> <html:checkbox property="married" value="yes"/> value="Diners"/> . . .

HTML tag
<input type="text" name="firstname"> <textarea name="address"> <input type="checkbox" name="married" value="yes"> <input type="radio" name="card" value="Diners"> . . . <select name="country"> <option value="F"> . . .

4. Radio button <html:radio property="card" 5. Selection list <html:select property="country"> and <html:option value="F"/> . . . single type 6. Selection list <html:select property="food" multiple="true"> and <html:option value="milk"/> . . . multiple type 7. List of checkboxes
<html:multibox property="site"> . . .

<select name="food" multiple> <option value="milk"> . . .

<input type="checkbox" name="site" value="jb"> <input type="checkbox" name="site" value="oj"> . . .

To begin with, you'll notice that where Struts uses the attribute name "property", HTML uses "name". This is a bit confusing since Struts also has an attribute called "name", which is used to give the name of the bean whose "property" maps the control. The default for the "name" attribute is the name of the form's corresponding bean, so normally you don't need to use the "name" attribute.

Mapping and accessing the controls


Rule # 1: The name of every control (given by the "property" attribute) must be dened in the form's bean, which may be:

2 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

1. a Java ActionForm bean dened in the form-beans section of the struts-cong le, for example:
<form-bean name="detailForm" type="hansen.playground.DetailForm"/>

2. a "dynamic" form bean, also dened in the form-beans section of struts-cong, for example:
<form-bean name="simpleForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="firstname" type="java.lang.String"/> <form-property name="site" type="java.lang.String[]"/> </form-bean>

Note that a control may be mapped to an array if it contains more than one value. Rule #2: You may get or set the data in the controls from the execute method in the Action class: 1. ActionForm bean:
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DetailForm df = (DetailForm)form; String index = df.getFirstName(); String[] site = df.getSite(); . . . df.setFirstName("John"); . . .

You may of course also get or set the data in the ActionForm itself - for example in the validate method. 2. Dynamic form bean:
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DynaActionForm f = (DynaActionForm)form; String firstName = (String)f.get("firstname"); String[] site = (String[])f.get("site"); . . . f.set("firstname", "John"); . . .

The "interesting" controls


We'll not spend time on the simple controls "Text eld", "Text area eld"" and "Checkbox" (marked 1, 2, and 3 in the tables above) since they're all "single-valued", and therefore simple to handle in

3 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

your classes. Instead we'll look further at the controls that have a set of options or values attached.

Set of xed options


Let's rst take care of the simple situation where the possible options of these controls are xed. By "xed" I mean that they won't change over time, for example "Male/Female" or "Spring/Summer /Autumn/Winter". The jsp-code example for such a control could be:
<html:radio property="sex" value="M"/>Male<br> <html:radio property="sex" value="F"/>Female

Another example with a multi selection list:


<html:select property="food" multiple="true"> <html:option value="milk">Milk</html:option> <html:option value="apple">Apple</html:option> <html:option value="bread">Bread</html:option> </html:select>

Dynamic options
It's much more interesting--seen from a programmer's point of view--when the selectable options are computed in the application, for example read from a database. Struts has solutions for all the remaining controls--marked 4, 5, 6, and 7 above--but unfortunately they're rather different. One thing is, however, common for some of them: they use the logic:iterate tag to loop over the set of selectable options. So let's take a quick recap of how to use the iterate tag. A simple example:
<table border=1> <logic:iterate id="customer" name="customers"> <tr> <td><bean:write name="customer" property="firstName"/></td> <td><bean:write name="customer" property="lastName"/></td> <td><bean:write name="customer" property="address"/></td> </tr> </logic:iterate> </table>

The iterate tag's name-attribute refers to a Collection of beans stored in request or session scope. The id-attribute gives the (logical) name of the bean created in each iteration. Other tags--for example the bean:write tag--may then refer to this bean with their name-attribute. The propertyattribute nally selects the wanted property from the bean. You might now think that you simply use the name- and property-attributes with the html-tags, but it's not that simple. The html-tags already use the property- attribute for the name of the property in the ActionForm, so there's a conict here. The tag inventors have had other challenges as well, so therefore the syntax for the HTML-tags when handling sets of options are a bit heterogeneous. The Radio Button Now I'll present a solution, and afterwards discuss the explanations. First the struts-cong le, where we dene a dynamic form bean (but you could just as well use the old ActionForm bean):

4 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

<form-bean name="radioForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="control" type="java.lang.String"/> </form-bean>

Then the jsp-code:


<logic:iterate id="choice" name="choices"> <html:radio property="control" idName="choice" value="value"/> <bean:write name="choice" property="label"/> <br> </logic:iterate>

We're using a Collection of beans with properties value and label. When the idName attribute is used the radio-tag's value-attribute denotes a property in the bean given by idName. It's the id-attribute in the iterate-tag and the idName in the radio-tag that links the tags together. Struts has a utility bean class called LabelValueBean with exactly these properties: value and label, and it may be used to construct a "minimal" bean to put in a Collection, for example:
import org.apache.struts.util.LabelValueBean; . . . Collection choices = new ArrayList(); choices.add(new LabelValueBean("American Express", "AE")); choices.add(new LabelValueBean("MasterCard", "MC")); choices.add(new LabelValueBean("Diners", "DN")); request.setAttribute("choices", choices);

You don't have to use this utility class, any bean will do, as long as it has properties that can be used for the value attribute in the html:radio tag and the property attribute in the bean:write tag. You may set or get the current value of the radio buttons in the execute method, as described earlier. The name we've used for the radio buttons, control, will also be used in the following examples. The Selection List - Single Type Since the single type selection list returns one value only, we can use the same setup in struts-cong as for the radio buttons:
<form-bean name="singleSelectForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="control" type="java.lang.String"/> </form-bean>

Now assume that we have a bean, Customer, with String properties firstName, lastName, address, and id. If you have a Collection of Customer beans then you can show a list of all the customers using jsp-code like this:
<html:select property="control" size="2"> <logic:iterate id="customer" name="customers" type="hansen.playground.Customer"> <html:option value="<%=customer.getId()%>"> <bean:write name="customer" property="firstName"/>

5 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

<bean:write name="customer" property="lastName"/> </html:option> </logic:iterate> </html:select>

You'll have to specify the type attribute of the iterate tag or the scriptlet will fail. There is a much nicer solution, however:
<html:select property="control" size="2"> <html:options collection="customers" property="id" labelProperty="fullName"/> </html:select>

This time we use the options tag, where the collection attribute gives the name of the Collection of beans, and property gives the name of the property in the bean whose value will be returned when the form is submitted. labelProperty is the bean property that will be displayed. I've created a pseudo-property, fullName, in the Customer bean with a getter-method that returns the firstName and the lastName. In the browser we could have this presented:

The generated HTML looks like this:


<select name="control" size="2"> <option value="001">John Doe</option> <option value="002" selected="selected">Peter Smith</option> </select>

An almost identical solution, but using less confusing attribute names, is this:
<html:select property="control" size="2"> <html:optionsCollection name="customers" value="id" label="fullName"/> </html:select>

The current value of the list is again set or get in the execute method--as described previously. The Selection List - multiple type You may copy the solutions from the single choice selection list if you add multiple="true" to the html:select-tag:
<html:select multiple="true" property="control" size="2"> <html:optionsCollection name="customers" value="id" label="fullName"/> </html:select>

This time, however, you'll have to dene the control property in the ActionForm as a String array:
<form-bean name="multiSelectForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="control" type="java.lang.String[]"/> </form-bean>

6 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

List of checkboxes Finally, the case with a set of checkboxes, where the user may select zero, one or many of the presented options. This resembles the multi selection list, only the GUI is different. You might think that a solution like this will work:
<logic:iterate id="customer" name="customers" type="hansen.playground.Customer"> <html:checkbox property="control" value="<%=customer.getId()%>"/> <bean:write name="customer" property="fullName"/> <br> </logic:iterate>

It will not work 100%. The GUI is OK, and you may also submit the correct data, but if you return to the same page you have lost the data you just typed in. There is, however, a special tag for this case called the multibox, and it will work:
<logic:iterate id="customer" name="customers"> <html:multibox property="control"> <bean:write name="customer" property="id"/> </html:multibox> <bean:write name="customer" property="fullName"/> <br> </logic:iterate>

In the browser you would see something like this:

Here's the generated HTML:


<input type="checkbox" name="control" value="001" checked="checked"> John Doe <br> <input type="checkbox" name="control" value="002"> Peter Smith <br>

Deselecting all choices


Consider the situation where you have either a list of checkboxes or a multi-selection list and have dened the Struts action in session scope. Take a look at this example:
<action path="/multicheckbox" type="hansen.playground.MultiCheckboxAction" scope="session" name="multiCheckboxForm"> <forward name="OK" path="/multicheckbox.jsp"/> </action>

7 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

If you deselect all choices and submit the form you'll observe that nothing happens: the previously selected values are still selected. The reason is, since you haven't selected anything, nothing is actually submitted. The ActionForm is therefore not updated. You may correct this behavior if you dene a reset method in your ActionForm that initializes the control's array to an empty array:
public void reset( ActionMapping mapping, HttpServletRequest request) { this.control = new String[0]; }

If you are using a DynaActionForm you'd have to code an extension of the DynaActionForm:
package hansen.playground; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.DynaActionForm; public class MyDynaActionForm extends DynaActionForm { public void reset( ActionMapping mapping, HttpServletRequest request) { this.set("control", new String[0]); } }

This situation only occurs for an action dened in session scope. In request scope you get a new bean for every request, with the control's property initially set to an empty array.

List of input elds


Let's nish by looking into how we could construct a list of text input elds. We'd like to present a page that looks like this:

The persons are taken from a database, so the number of "lines" is a variable. This is a case for Struts' "Indexed Properties". We'll once more use the Customer class, so rst we dene this form in struts-cong:
<form-bean name="listTextForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="customer" type="hansen.playground.Customer[]"/> </form-bean>

8 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

This is a very different setup from what we have seen before. This time we dene a "control" which is an array of Customers. The action in the struts-cong must have scope="session":
<action path="/listtext" type="hansen.playground.ListTextAction" scope="session" name="listTextForm"> <forward name="OK" path="/listtext.jsp"/> </action>

Now the Action class:


public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DynaActionForm f = (DynaActionForm) form; Customer[] s = (Customer[])f.get("customer"); if (s.length == 0) { // First time in this class Collection c = new ArrayList(); Customer cust1 = new Customer("001", "John", "Doe", "X-Street 7"); Customer cust2 = new Customer("002", "Peter", "Smith", "Computer blvd. 123"); Customer cust3 = new Customer("003", "Keld", "Hansen", "Java Road 13"); c.add(cust1); c.add(cust2); c.add(cust3); Customer[] cs = (Customer[])c.toArray(new Customer[0]); f.set("customer", cs); } else { // We've been here before for (int i = 0; i < s.length; i++) { Customer c = (Customer)s[i]; String t = c.getFullName(); System.out.println(t); // For debugging } } return (mapping.findForward("OK")); ...

This time we get an array of Customers in the ActionForm. The jsp-page could look like this:
<html:form action="listtext"> <html:submit/> <logic:iterate id="customer" <html:text name="customer" <html:text name="customer" <html:text name="customer" <br> name="listTextForm" property="customer"> property="firstName" indexed="true"/> property="lastName" indexed="true"/> property="address" indexed="true"/>

9 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

</logic:iterate> </html:form>

The new thing here is the indexed attribute. We iterate over the array of Customers, and for each bean we use its attributes in the text elds. Note that we'll have to use the name "customer" in several places to have the Indexed Properties feature working. If you were to look in the generated HTML you would see this:
<input type="text" name="customer[0].firstName" value="John"> <input type="text" name="customer[0].lastName" value="Doe"> <input type="text" name="customer[0].address" value="X-Street 7"> <br> <input type="text" name="customer[1].firstName" value="Peter"> <input type="text" name="customer[1].lastName" value="Smith"> <input type="text" name="customer[1].address" value="Computer blvd. 123"> <br> <input type="text" name="customer[2].firstName" value="Keld"> <input type="text" name="customer[2].lastName" value="Hansen"> <input type="text" name="customer[2].address" value="Java Road 13"> <br>

When such a form is submitted Struts will recognize the syntax of the name-attributes as Indexed Properties, and ll the ActionForm correctly. This setup will also work for lists of other controls as well. Read more about Indexed Properties in the Struts documentation.

Recap
1. Always dene properties in the ActionForm matching the property attribute from the html-tag. The exception is Indexed Properties, where you must dene an array of the object you iterate through 2. Use setters and getters from the ActionForm to access the data in the form. 3. Use these tags in your jsp: Radiobuttons
<logic:iterate id="customer" name="customers"> <html:radio property="control" idName="customer" value="id"/> <bean:write name="customer" property="fullName"/> <br> </logic:iterate> <html:select property="control" size="2"> <html:optionsCollection name="customers" value="id" label="fullName"/> </html:select> <html:select property="control" size="2" multiple="true"> <html:optionsCollection name="customers" value="id" label="fullName"/> </html:select> <logic:iterate id="customer" name="customers"> <html:multibox property="control"> <bean:write name="customer" property="id"/> </html:multibox>

Selection list - single value Selection list - multiple values List of checkboxes

10 de 11

17/01/12 06:37

JavaBoutique - Advanced Forms Handling in Struts 1.1

http://javaboutique.internet.com/tutorials/strutsform/article.html

List of text elds

<bean:write name="customer" property="fullName"/> <br> </logic:iterate> <logic:iterate id="customer" name="listTextForm" property="customer"> <html:text name="customer" property="firstName" indexed="true"/> <html:text name="customer" property="lastName" indexed="true"/> <html:text name="customer" property="address" indexed="true"/> <br> </logic:iterate>

Conclusion
Struts has a rich set of HTML-tags for building form controls. Unfortunately it's often rather difcult to predict the exact syntax to use in a given situation. The examples presented above should be possible to copy/paste into your own applications. If you dig up another clever solution you're welcome to e-mail me, and I'll try to put your solution in one of my upcoming articles. Happy coding! Keld is currently working as a web architect for one of the largest IT companies in Denmark. He battled with the mainframes during the 70's when they were the size of a gymnasium and had the power of your PalmPilot. He also struggled with CASE-tools in the 90s and now explores the cutting edge technology of the Web. While not busy at his computer he likes to vacation on the Greek islands.

Resources
A zip le with all examples from the article The home of Struts: jakarta.apache.org/struts Struts' User and Developer Guide Struts' documentation on the HTML-tags Previous articles from JavaBoutique about Struts: - "Stepping through Jakarta Struts" - "Coding your second Jakarta Struts Application" - "Introducing: the Struts bean and logic Tag Libraries" - "Stepping through the Struts 1.1 Validator" - "StrutsTestCase: The Tool for Struts Unit testing" - "Handling Messages, Errors and Exceptions in Struts 1.1" "Succeeding With Struts: Indexed Properties and Beans as Properties" Tips on various forms questions, by Ted Husted

11 de 11

17/01/12 06:37

You might also like