Matt RaibleMatt Raible is a Web Developer and Java Champion. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Struts Validator: Validating Two Fields Match

In the Struts Validator Guide, there is a section on how to create a pluggable validator that matches two fields. I've been using this server-side validator (as shown in the example) to do password/confirm password validation. This has worked great for me, but I've always wanted the Validator to have the client-side JavaScript method for it too. I wrote my own that just compared the two fields, but it's not the same as having one rendered for you (from validator-rules.xml). So yesterday, I did some tinkering and figured out how to add the JavaScript method to validator-rules.xml. So here's how to configure the whole thing (most of this is contained in the Validator Guide, save the JavaScript).

How To Add a TwoFields Validator

Step 1: Create a class with a validateTwoFields method. In my code, my class is ValidationUtil and has the following method:

public static boolean validateTwoFields(Object bean, ValidatorAction va,
                                        Field field, ActionErrors errors,
                                        HttpServletRequest request) {
    String value =
        ValidatorUtil.getValueAsString(bean, field.getProperty());
    String sProperty2 = field.getVarValue("secondProperty");
    String value2 = ValidatorUtil.getValueAsString(bean, sProperty2);

    if (!GenericValidator.isBlankOrNull(value)) {
        try {
            if (!value.equals(value2)) {
                errors.add(field.getKey(),
                           Resources.getActionError(request, va, field));

                return false;
            }
        } catch (Exception e) {
            errors.add(field.getKey(),
                       Resources.getActionError(request, va, field));

            return false;
        }
    }

    return true;
}

Step 2: Edit validator-rules.xml to contain the "twofields" rule.

<validator name="twofields" 
    classname="org.appfuse.webapp.util.ValidationUtil" method="validateTwoFields" 
    methodParams="java.lang.Object,
                  org.apache.commons.validator.ValidatorAction,
                  org.apache.commons.validator.Field,
                  org.apache.struts.action.ActionErrors,
                  javax.servlet.http.HttpServletRequest" 
   depends="required" msg="errors.twofields">
    <javascript><![CDATA[
        function validateTwoFields(form) {
            var bValid = true;
            var focusField = null;
            var i = 0;
            var fields = new Array();
            oTwoFields = new twofields();
            for (x in oTwoFields) {
                var field = form[oTwoFields[x][0]];
                var secondField = form[oTwoFields[x][2]("secondProperty")];
            
                if (field.type == 'text' ||
                    field.type == 'textarea' ||
                    field.type == 'select-one' ||
                    field.type == 'radio' ||
                    field.type == 'password') {
            
                    var value;
                    var secondValue;
                    // get field's value
                    if (field.type == "select-one") {
                        var si = field.selectedIndex;
                        value = field.options[si].value;
                        secondValue = secondField.options[si].value;
                    } else {
                        value = field.value;
                        secondValue = secondField.value;
                    }
                
                    if (value != secondValue) {
                    
                        if (i == 0) {
                            focusField = field;
                        }
                        fields[i++] = oTwoFields[x][1];
                        bValid = false;
                    }
                }
            }
            
            if (fields.length > 0) {
                focusField.focus();
                alert(fields.join('\n'));
            }
            
            return bValid;
        }]]></javascript>
</validator>

Step 3: Configure validation for your form in validation.xml:

<field property="password"
     depends="required,twofields">
  <msg
    name="required"
    key="errors.required"/>
  <msg
    name="twofields"
    key="errors.twofields"/>

  <arg0 key="userForm.password"/>
  <arg1
    key="userForm.confirmPassword"
  />
  <var>
    <var-name>secondProperty</var-name>
    <var-value>confirmPassword</var-value>
  </var>
</field>

Where errors.twofields=The '{0}' field has to have the same value as the '{1}' field. An alternative to Step 3 is to use XDoclet to generate your validation.xml. This requires (1) configuring XDoclet (of course) and (2) adding some @struts tags to your form on the setPassword method.

/**
 * Returns the password.
 * @return String
 *
 * @struts.validator type="required" msgkey="errors.required"
 * @struts.validator type="twofields" msgkey="errors.twofields"
 * @struts.validator-args arg1resource="userForm.password"
 * @struts.validator-args arg1resource="userForm.confirmPassword"
 * @struts.validator-var name="secondProperty" value="confirmPassword"
 */
public String setPassword() {
	return password;
}

I've sent this as a proposal to the struts-dev mailing list yesterday, but haven't heard anything yet. Enjoy!

Update: You'll need to update ValidationUtil.java and validator-rules-custom.xml for Struts 1.2. Full files: ValidationUtil.java and validation-rules-custom.xml.

Posted in Java at Feb 26 2003, 12:29:56 PM MST 10 Comments
Comments:

Oh my god this is painful.... having javascript put in for you is nice and all, but... yuck. Check out the validation stuff I put into Xwork. Combine a quick and simple ExpressionValidator with "password1 == password2" and a template for 2 password fields with some javascript which you can easily turn into a jsp tag like the rest of the ui tags we've got, and you've got a much simpler solution.

Posted by Jason Carreira on February 27, 2003 at 06:14 PM MST #

IMO there's really nothing to it. For the most part, all the validators I've needed have been written in the core validator stuff. This includes server-side and client-side stuff. You guys should look into using the Commons Validator - why re-invent the wheel? You could at least borrow the stuff for client side validation of e-mails, credit cards, regular expressions, etc...

Posted by Matt Raible on February 28, 2003 at 04:48 AM MST #

I need some advice.I develop a program to accept date with the fomrat of MM/dd/yyyy. I have defined the datePattern MM/dd/yyyy in validator.xml. When i run the program and give an input - 04/12/2003 it says that the date validation is FAILED. can anyone help me with this? I think i have provide the right format. tq

Posted by icemankimi on July 08, 2003 at 09:02 AM MDT #

Why reinvent the wheel - I've been using Fortran for over 30 years now and I've never had to.......

Posted by Anon-II on May 04, 2004 at 10:35 PM MDT #

This is really great, Matt.

Posted by John Norman on May 27, 2004 at 12:41 AM MDT #

I am a beginner of struts.Would you show the details of org.appfuse.webapp.util.ValidationUtil.Thanks.

Posted by rainer on July 04, 2004 at 01:25 PM MDT #

Here's the source from AppFuse's CVS: ValidationUtil.java.

Posted by Matt Raible on July 04, 2004 at 09:44 PM MDT #

!If you are using Struts 1.2, this rule can be implemented using the new <code>validwhen</code> Validator rule. {{{ <field property="password2" depends="required,validwhen"> <arg key="prompt.password2"/> <msg name="validwhen" key="error.password.match"/> <var> <var-name>test</var-name> <var-value>(*this* == password)</var-value> </var> </field> }}}

Posted by Bill Siggelkow on July 12, 2004 at 05:14 AM MDT #

Hi, I tried to write custom validation rule called "identical". But, if I give oIdentical = new identical(); I didn't get any client side alert messages. Hope this statement doesn't generate necessary javascript code when the rule is configured and executed. I'm using Struts 1.2.1 (Beta). Could you pl tell me the use of oTwoFields = new twofields(); statement and how struts uses this statement to generate client side javascript. Thanx in advance, Ratnakar

Posted by Ratnakar on August 06, 2004 at 01:59 PM MDT #

I took a look at Struts 1.2.4 and while "validwhen" exists, it doesn't have a client-side component. I wasn't aware of "identical", but I'm guessing it's the same scenario.

BTW, I did have to update the above script for 1.2.

Posted by Matt Raible on October 01, 2004 at 02:29 PM MDT #

Post a Comment:
Comments are closed for this entry.