Lazy Validator Form

Java LazyValidatorForm - Working With

1. Information about LazyValidatorForm

LazyValidatorForm has now been donated to Struts and is available in Version 1.2.6 onwards.

For information on LazyValidatorForm see the JavaDoc.

See also the Lazy DynaBean page.

The rest of this page has the following sections:

  • 2. Using the LazyValidatorForm in Struts
  • 3. Controlling Properties via struts-config.xml
  • 4. Custom Implementations - NestedLazyForm Example
  • 5. Retaining the Firewall behaviour of the ActionForm

2. Using the LazyValidatorForm in Struts

Define the form in the struts-config.xml:

<struts-config>
<form-beans>
<form-bean name="lazyForm" type="org.apache.struts.validator.LazyValidatorForm"/>
</form-beans>
<action-mappings>
<action path="/myActionPath" type="myPackage.MyAction" name="lazyForm" validate="true"/>
</action-mappings>
</struts-config>

Set up the jsp in the usual way.

<html:form action="/myActionPath">
<h2>Simple Property Example</h2>
Customer Number: <html:text property="custNo"/>
Customer Name:   <html:text property="custName"/>
<h2>Mapped Property Example</h2>
Street:  <html:text property="address(street)"/>
Town:    <html:text property="address(town)"/>
State:   <html:text property="address(state)"/>
Country: <html:text property="address(country)"/>
<h2>Indexed Property Example</h2>
<logic:iterate id="products" property="products">
Product Code:        <html:text name="products" property="code"        indexed="true"/>
Product Description: <html:text name="products" property="description" indexed="true"/>
Product Price:       <html:text name="products" property="price"       indexed="true"/>
</logic:iterate>
</html:form>

Use in the Action by casting the ActionForm to a DynaBean.

public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServeletRequest request,
HttpServletResponse response) throws Exception {
// Cast form to DynaBean
DynaBean dynaForm = (DynaBean)form;
// Use the DynaBean
String custNo = (String)dynaForm.get("custNo");   // simple
Map address   = (Map)dynaForm.get("address");     // mapped
List products = (List)dynaForm.get("products");   // indexed  
... etc etc
}

N.B. One of the stated functions of an ActionForm in Struts is to act as a Firewall between the request and the Action - only properties defined in the ActionForm are populated from the request. Using the Lazy implementations in this way circumvents this - everything in the request parameters get populated to the Lazy ActionForms. This means that you need to make sure that you only take out of these ActionForms what should be in there.

3. Controlling LazyValidatorForm Properties via struts-config.xml

These lazy ActionForms, by default, create an java.util.ArrayList for indexed properties and a java.util.HashMap for mapped properties. If however you want to use alternative implementations then you can define these properties in the struts-config.xml in the same way as for a DynaActionForm.

For example, using an array of lazy beans:

<form-bean name="myForm" type="org.apache.struts.validator.LazyValidatorForm">
<form-property name="myArray" type="org.apache.commons.beanutils.LazyDynaBean[]"/>
</form-bean>

.. or an array of regular java beans:

<form-bean name="myForm" type="org.apache.struts.validator.LazyValidatorForm">
<form-property name="myArray" type="myPackage.MyCustomBean[]"/>
</form-bean>

.. or an alternative Map implementatiom:

<form-bean name="myForm" type="org.apache.struts.validator.LazyValidatorForm">
<form-property name="myMap" type="java.util.TreeMap"/>
</form-bean>

You may ask "well doesn't this defeat the purpose of using lazy ActionForms?" - yes to a certain extent, but you still don't have to define all the simple properties and you still get the benefit lazy list type behaviour with the array or List being automatically grown to the appropriate size.

4 Custom Implementations of LazyValidatorForm  - NestedLazyForm Example

If, for example, you always wanted certain implementations for mapped or indexed properties then there is an alternative approach to using the struts-config.xml - create your own custom LazyDynaBean overriding the defaultMappedProperty() or defaultIndexedProperty() methods and plug those into your own lazy ActionForm. The NestedDynaBean is an example custom implementation the source code for which is available here.

The code below shows how to implement this custom NestedLazyBean into your own custom Lazy ActionForm.

import org.apache.commons.beanutils.DynaBean;
import org.apache.struts.validator.LazyValidatorForm;
public class NestedLazyForm extends LazyValidatorForm {
/**
* Constructor which installs a NestedLazyBean as the DynaBean
* backing this Lazy ActionForm.
*/
public NestedLazyForm() {
super(new NestedLazyBean());
}
/**
* Override the default indexed bean property to be a NestedLazyBean.
* (This only affects List type indexed properties).
*/
protected DynaBean newIndexedBean(String name) {
return new NestedLazyBean();
}
}

NOTE: If you want a flavour that validates according to the Action Mapping's path rather than the Action Mapping's form, then you just need to call the setPathValidation() method with a value of true in the constructor.

5. Retaining the Firewall behaviour of the ActionForm

If you just want to use the Lazy list features and retain the Firewall function of the ActionForm then you can do this by defining all the properties in the struts-config.xml in the same way as for a DynaActionForm and setting the restricted property. The restricted property makes the MutableDynaClass restricted which prevents any additional properties being added.

<struts-config>
<form-beans>
<form-bean name="restrictedForm" type="org.apache.struts.validator.LazyValidatorForm">
<set-property property="restricted" value="true"/>
<form-property name="orderNumber" type="java.lang.Integer" />
<form-property name="customerName" type="java.lang.String" />
<form-property name="orderValue" type="java.lang.BigDecimal" />
<form-property name="orderLines" type="org.apache.commons.beanutils.LazyDynaBean[]" />
</form-bean>
</form-beans>
</struts-config>