# Validating User Input

In most cases when a user enters data through a form, we want to ensure that the values entered are valid before the data is, for instance, stored in a database or used to determine the next action. Form validation is frequently done using client-side JavaScript. This approach is also possible in WebLogic Workshop. In addition, server-side validation checks the user input on the server side. The advantages of the latter approach:

- You do not have to rely on the features of the browser, over which you have no control.
- You can encapsulate the validation logic with the other business logic in the controller file.
- Error messages can be displayed right in the form next to the affected form field, instead of in popup dialogs.

## Client-Side Validation

WebLogic Workshop provides a number of attributes on the <netui:form> tag and its form fields, such as onClick and onBlur, which can be used to invoke JavaScript. For example, you can have a <netui:textBox> tag in which a user enters his age:

        <netui:textBox dataSource="{actionForm.age}" onBlur="isValidAge()"/>

This is an example of the JavaScript function isValidAge which is mentioned in the onBlur attribute:

        function isValidAge() {
            if(document.forms[0].elements[1].value <= 0)
                alert('Wrong Age');
        }

After the user has entered a value and goes to the next form field, the onBlur attribute calls the JavaScript function isValidAge, which will display a dialog when the age is not considered valid.

Notice that in the example the form and its fields are accessed by using JavaScript forms and elements arrays. If you would like to use the id attributes to access the form and its fields, you need to (1) specify the tagID attributes on the <netui:form> and its input elements. Then use the JavaScript function getNetuiTagName(tagId, this). Also, you will need to ensure that the <html> tag is replaced with <netui:html> on the JSP page. Rewriting the previous example, the code will be:

    <netui:html>
         ...
         <netui:form tagId="myForm" >
             <netui:textBox tagId="age" dataSource="{actionForm.age}" onBlur="isValidAge();"/>
         </netui:form>
         ...
    </netui:html>

And this would be the JavaScript function isValidAge:

    function isValidAge() {
        if(document.forms[getNetuiTagName("myForm",this)][getNetuiTagName("age",this)].value <= 0)
            alert('Wrong Age');
    }

Notice that instead of using elements[1], we refer to the element's tagID using the function getNetuiTagName( tagId, this ).

These approaches also work in conjunction with a submit action of the form. For <netui:button> and <netui:imageButton> tags, you can invoke the JavaScript function through the tags's onClick attribute, as is shown in the following example:

    <netui:button value="submit" onClick="return isValidForm();" />

When a user clicks the button, a JavaScript function isValidForm checks the form fields and returns true if validation is successful. Or the isValidForm function displays a dialog with error messages and returns false if not all entered values are correct. (The implementation of this function is not actually shown in the sample code.)

For <netui:anchor> and <netui:imageAnchor> tags, whose implementation rely on JavaScript to submit a form, your JavaScript validation function must contain additional code to set the method and action properties of the JavaScript Form object, and call its submit method if validation is successful. The following example, which uses the same tagIDs and JavaScript function isValidForm as the previous example, demonstrates how to set the various properties and invoke the submit method when form validation is successful:

    function submitFromAnchor() {
        document.forms[getNetuiTagName("myForm",this)].method="POST";
        document.forms[getNetuiTagName("myForm",this)].action="/ClientSideValidation/thankYou.do";
        if(isValidForm())
            document.forms[getNetuiTagName("myForm",this)].submit();
    }

As shown in the example, the form's method property must be set to POST. The action property must be set to the full name of the action to be called when the user clicks the anchor and submits the form. This action name corresponds to the web application name followed by the name of the action method in the JPF file, followed by a DO extension. In the example, the page flow JPF file of the web application ClientSideValidation contains an action method thankYou.

The same function could have been written without the use of getNetuiTagName( tagId, this ), as shown in the following example:

    function submitFromAnchor() {
        document.forms[0].method="POST";
        document.forms[0].action="/ClientSideValidation/thankYou.do";
        if(isValidForm())
             document.forms[0].submit();
    }

However, if your application resides in a Portal application, it is recommended that you use getNetuiTagName(tagId, this) to retrieve page elements, since Portal containers may rewrite the id attributes of page elements. For details see Using JavaScript in Page Flow and Portal Applications.

Finally, the <netui:anchor> or <netui:imageAnchor> tags must call the JavaScript function in the onClick attribute and add "return false;" as is shown in the following example:

    <netui:anchor onClick="submitFromAnchor(); return false;" action="thankYou">Submit</netui:anchor>

If you do not add the expression "return false;", the form will always be submitted and no data will be posted to the form bean.

For more information on using client-side JavaScript see Using JavaScript in Page Flow and Portal Applications.

## Server-Side Validation

WebLogic Workshop offers two ways to accomplish server-side validation, one using Java to implement the validate method in the form bean, and the other using the Struts ValidatorPlugIn to do XML-based validation. These examples are shown in the WebLogic Workshop sample application, and are described here. For the sample code, start in the following installed location:

<WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/validation/...

### Java-Based Validation

To validate user input using the form bean's validate method, follow the steps outlined in this list. Note that these examples are from the following sample page flow, and associated files:

<WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/validation/basic

- Add a message-resources tag to your controller class in the JPF File, for example:

      /**
       * @jpf:controller nested="true"
       * @jpf:message-resources resources="validation.basic.Messages"
       *
       */
      public class Controller extends PageFlowController
      {
      ...

  The resources file is located under the web project's /WEB-INF/classes/... folder and has a properties extension. In the example above the Messages.properties file is located in /WEB-INF/classes/validation/basic. The contents of this file are described below.

  Note: In the example, notice the corresponding naming requirements in use here. If the messages resource file is <project-root>/WEB-INF/classes/validation/basic/Messages.properties, then the way to reference this file in the <project-root>/validation/basic/*.jpf page flow annotation is @jpf:message-resources resources="validation.basic.Messages".

- Add a @jpf:validation-error-forward annotation to the action that uses validation. For example:

       /**
        * @jpf:action
        * @jpf:forward name="success" path="success.jsp"
        * @jpf:validation-error-forward name="failure" return-to="currentPage"
        */
        public Forward submitForm( Form form )
        {
           return new Forward( "success" );
        }

  This annotation provides a flexible mechanism to indicate which page should be loaded, or which action should be run, if a form validation error occurs as a result of running the annotated action. For details see the @jpf:validation-error-forward Annotation topic.

  The following Flow View screen illustrates the relationship of the actions and pages in this sample page flow.

- Add the validate method to your form bean class. This method must have the exact signature as given in the example:

      public ActionErrors validate( ActionMapping mapping, HttpServletRequest request )
      {
          ActionErrors errs = new ActionErrors();

          int at = _email.indexOf( '@' );
          int dot = _email.lastIndexOf( '.' );

          if ( at == -1 || at == 0 || dot == -1 || at > dot )
          {
             errs.add( "email", new ActionError( "badEmail" ) );
          }

          if ( _zipCode.length() != 5 )
          {
             errs.add( "zipCode", new ActionError( "badZip", new Integer( 5 ) ) );
          }

          return errs;
      }

  In the validate method you implement the validation logic for the various form fields. If there is an error, you add a new action error. In the example, zipCode refers to a <netui:error> tag in your JSP (<netui:error value="zipCode"/>), and badZip refers to the message key in the Messages.properties file. Note that the new Integer(5) is an object that is the first replacement in the error string. For example, later in this description you will see that we have a message string: "The zip code has to be exactly {0} characters." In this case, the {0} will be replaced by the Integer(5) object. ActionErrors supports constructors with up to four additional replacement objects.

  For the full example, see the page flow controller class at <WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/validation/basic/Controller.jpf.

- In the JSP file that displays errors (typically the form page), add the <netui:error> tags to display error messages. For example:

          <netui:form action="submitForm">
              <table>
                  <tr>
                      <td><p>Enter E-mail Address:</p></td>
                      <td>
                          <netui:textBox dataSource="{actionForm.email}"/>
                      </td>
                      <td>
                          <netui:error value="email"/>
                      </td>
                  </tr>

                  <tr>
                      <td><p>Enter 5-digit Zip Code:</p></td>
                      <td>
                          <netui:textBox dataSource="{actionForm.zipCode}"/>
                      </td>
                      <td>
                          <netui:error value="zipCode"/>
                      </td>
                  </tr>
              </table>

              <netui:button>Submit</netui:button>
              <netui:button action="exit">Exit</netui:button>
          </netui:form>

  In the example an error will be displayed next to the relevant form field. For the full example, see
  <WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/struts/validation/basic/formPage.jsp.

- In addition, or as an alternative, you can add a <netui:errors> tag to your JSP (<netui:errors/>), for instance at the bottom of your JSP. This tag will display a summary of all the errors that were found.
- The resources file contains the actual error message plus any special html formatting you might want to apply when displaying the errors in the JSP. Remember that this file is located under /WEB-INF/classes/... and has a properties extension. In this example, the Messages.properties file is located in /WEB-INF/classes/validation/basic.

      badEmail=Bad email address.
      badZip=The zip code has to be exactly {0} characters.

      errors.header=<br><hr><font color="Blue">List of errors, using the &lt;netui:error&gt; tag:<ul>
      errors.prefix=<li>
      errors.suffix=
      errors.footer=</ul></font>

      error.prefix=<font color="Red">
      error.suffix=</font>

  Notice that in the example, badZip is the message key for the error message that needs to be displayed when an incorrect zipCode was entered. The other lines in the file create formatting for the <netui:error> and <netui:errors> tags, such that individual error messages are displayed in red and the error summary is displayed in blue as a list, preceded by the header "List of errors, using the <netui:error> tag:".

### XML-Based Validation

To validate user input using the Struts ValidatorPlugIn, follow the steps outlined in this list. Note that these examples are from the following sample page flow, and associated files:

<WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/validation/validator

- Add message-resources and struts-merge annotations to your controller class in the JPF File. For example:

      /**
       * @jpf:controller nested="true" struts-merge="/WEB-INF/strutsValidator-merge-config.xml"
       * @jpf:message-resources resources="validation.validator.Messages"
       *
       */
      public class Controller extends PageFlowController
      {
      ...

  The @jpf:controller annotation's struts-merge attribute identifies the Struts merge file we will use. This Struts merge file will point to the Struts ValidatorPlugIn and its rules. The merge file is described later in this list.

  Also, the resources file is located under the web project's /WEB-INF/classes/... folder and has a properties extension. In the example above the Messages.properties file is located in /WEB-INF/classes/validation/validator. Notice the corresponding naming requirements in use here. If the messages resource file is <project-root>/WEB-INF/classes/validation/validator/Messages.properties, then the way to reference this file in the <project-root>/validation/validator/*.jpf page flow annotation is @jpf:message-resources resources="validation.validator.Messages".

- Add a @jpf:validation-error-forward annotation to the action that uses validation. For example:

      /**
       * @jpf:action
       * @jpf:validation-error-forward name="failure" return-to="currentPage"
       * @jpf:forward name="success" path="success.jsp"
       */
      public Forward submitForm( MyForm form )
      {
          return new Forward( "success" );
      }

  This annotation provides a flexible mechanism to indicate which page should be loaded, or which action should be run, if a form validation error occurs as a result of running the annotated action. For details see the @jpf:validation-error-forward Annotation topic.

- In the page flow, modify your form bean definition to extend Struts' ValidatorForm interface:

       public static class MyForm extends org.apache.struts.validator.ValidatorForm
       {
       ...

  For the full example of this form bean class, see <WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/validation/validator/Controller.jpf.
- In the JSP file that displays errors (typically the form page), add the <netui:error> tags to display error messages:

          <netui:form action="submitForm">
              <table>
                  <tr>
                      <td><p>Enter E-mail address:</p></td>
                      <td>
                          <netui:textBox dataSource="{actionForm.email}"/>
                      </td>
                      <td>
                          <netui:error value="email"/>
                      </td>
                  </tr>

                  <tr>
                      <td><p>Enter Age:</p></td>
                      <td>
                          <netui:textBox dataSource="{actionForm.age}"/>
                      </td>
                      <td>
                      <netui:error value="age"/>
                      </td>
                  </tr>
              </table>

              <netui:button>Submit</netui:button>
              <netui:button action="exit">Exit</netui:button>
          </netui:form>

  In the example an error will be displayed next to the relevant form field. For the full example, see <WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/validation/validator/formPage.jsp.

- In addition, or as an alternative, you can add a <netui:errors> tag to your JSP (<netui:errors/>), for instance at the bottom of your JSP. This tag will display a listing of all the errors that were found.
- Define the struts-merge file to point to Struts' default pluggable validator definition file validator-rules.xml as well as the XML file containing the actual validation rules for this particular form. In our example, the merge file strutsValidator-merge-config.xml is defined as follows. You can find this merge file in:

  <WEBLOGIC_HOME>/samples/workshop/SamplesApp/WebApp/WEB-INF

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
        "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

      <struts-config>
         <form-beans/>
         <global-exceptions/>
         <global-forwards/>
         <action-mappings>
         </action-mappings>

       <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
         <set-property property="pathnames"
         value="/WEB-INF/validator-rules.xml,/WEB-INF/strutsValidator-validation.xml"/>
       </plug-in>

      </struts-config>

  The default pluggable validator definitions are contained in the file validator-rules.xml, which is located in WEB-INF. The actual form validation rules should be defined in a separate file. In the example the file is called strutsValidator-validation.xml and is also located in /WEB-INF. This file is described next.

- In the file strutsValidator-validation.xml, you implement the actual form validation using the default validator definitions. For example:

      <form-validation>
          <formset>
              <form name="myForm">
                  <field property="email" depends="required">
                      <arg0 key="email.displayName"/>
                  </field>
                  <field property="age" depends="required,integer">
                      <arg0 key="age.displayName"/>
                  </field>
              </form>
          </formset>
      </form-validation>

- The resources file contains the actual error message plus any special html formatting you might want to apply when displaying the errors in the JSP file. Remember that this file is located under WEB-INF/classes/... and has a properties extension. In this example, the Messages.properties file is located in /WEB-INF/classes/validation/validator.

      errors.header=<br><hr><font color="Blue">List of errors, using the &lt;netui:error&gt; tag:<ul>
      errors.prefix=<li>
      errors.suffix=
      errors.footer=</ul></font>

      error.prefix=<font color="Red">
      error.suffix=</font>

      errors.required={0} is required.
      errors.integer={0} must be an integer.

      email.displayName=The email address
      age.displayName=The age

  Notice that in the example, email.displayName describes the name of a form field, whereas errors.required describes the error message for missing but required form field entries. If a user does not type in an e-mail address, the resulting error message will be "The email address is required". The other lines in the file create formatting for the <netui:error> and <netui:errors> tags, such that individual error messages are displayed in red and the error summary is displayed in blue as a list, preceded by the header "List of errors, using <netui:error> tag:".

Related Topics

@jpf:validation-error-forward Annotation

@jpf:message-resources Annotation

Validating User Data with Struts Sample

Merging Struts Artifacts Into Page Flows

Using JavaScript in Page Flow and Portal Applications