Monday, December 1, 2003

Using a reusable code approach to HTML select option lists, part V

This is a very simple module, but in order for it to work, it needs two pieces of information:

  • the name of the OptionListSourceFactory that we will be using to produce our OptionListSource object;
  • The name of the OptionListSource object that we need to pass to the factory in order to obtain the source that is applicable to the field being validated.

If you have been following along in this series, you may wonder why we need to pass the name of the factory to the validator since we only created one factory and made no provisions for a collection of factory variations. While that is true, that is just the nature of the shortcut we took to introduce the factory concept. For a complete, production-grade implementation of the factory concept, you should have a factory interface just as we have an OptionListSource interface, and factories should be produced based on a common set of base code contained in an abstract class. Since we elected not to do that, we don't really need to pass the class name of the factory to our validator, but I included that step in here, just because that's really the way it ought to be done.

Once our validator has obtained the option list from the OptionListSource (which it obtained from the factory using the name parameter provided) all that is left for it to do is to iterate through the list of valid values and determine if the user input is on the list. If not, it simply notifies the Struts validation framework and lets the built-in validation features of that framework take care of the rest of the work. All in all, it works out pretty slick thanks to most of the work already being provided by Struts.

Configuring the validator

To make this all work, there are still two more things to do:

  • Define the validator in the Struts validator-rules.xml file;
  • Set up any field validations that you want to have use our new validator.

The entry in the validator-rules.xml is presented here:


      <validator name="validValues"
            classname="step.five.ValidValuesValidator"
               method="validateValidValues"
         methodParams="java.lang.Object,
                       org.apache.commons.validator.ValidatorAction,
                       org.apache.commons.validator.Field,
                       org.apache.struts.action.ActionErrors,
                       javax.servlet.http.HttpServletRequest"
                  msg="errors.valid.values">

         <javascript><![CDATA[
            function validateValidValues(form) {
                return true;
            }

            ]]>
         </javascript>

      </validator>

Next up is a sample of what a field validation entry in the validation.xml file would look like:


            <field property="priority"
                    depends="required,validValues">
                <arg0   key="label.priority"/>
                <var>
                    <var-name>factoryClass</var-name>
                    <var-value>step.five.OptionListSourceFactory</var-value>
                </var>
                <var>
                    <var-name>optionListName</var-name>
                    <var-value>priority</var-value>
                </var>
            </field>