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>
|