Search code examples
javavalidationstruts2struts-validationstruts2-convention-plugin

Reusing Custom Expression Validator in Struts 2


In Struts 2 we can develop @CustomValidator which can be used in application wide

@CustomValidator(type = "CustomerNumberValidator", fieldName = "customerNo")

For validation more than one field we use @ExpressionValidator

@ExpressionValidator(expression = 
"( (!''.equals(account.firstName) && (!''.equals(account.lastName) )
   || (presonalAccount == false)", 
   key = "validate.account.name")

If the expression is too complicated and needs to work on more than one field we use OGNL to call the static method. The static method will do the validation and return a boolean for example

@ExpressionValidator(expression = "@foo.bar.CalendarUtil@compareDates(fromDate,toDate)", key = "validate.date.before")

Above is some how a Custom Expression Validator !

And we use @foo.bar.CalendarUtil@compareDates in application wide to make this validation for us.

Is there another approach which enables us to use a custom wide validator?!

Is there any custom expression validator which can be added to Struts and we can call it in Action in the way we use @CustomValidator?


Solution

  • Create a Custom Validator (not field related):

    public final class CompareDatesValidator extends ValidatorSupport {
        private String fromDate; // getter and setter
        private String toDate;   // getter and setter    
    
        @Override
        public void validate(Object o) throws ValidationException {
            Date d1 = (Date)parse(fromDate, Date.class);
            Date d2 = (Date)parse(toDate, Date.class);
    
            if (d1==null || d2==null || d2.before(d1)){
                addActionError(getDefaultMessage());
            }
        }
    }
    

    Register the custom validator in validators.xml file:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE validators PUBLIC
         "-//OpenSymphony Group//XWork Validator Config 1.0//EN"
         "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
    <validators>
        <validator name="compareDatesValidator" 
                  class="org.foo.bar.CompareDatesValidator"/>
    </validators>
    

    Use the validator in an action:

    private Date startDate; // getter and setter
    private Date endDate;   // getter and setter
    
    @Validations(
        customValidators={
            @CustomValidator(type="compareDatesValidator", 
                message="Dates provided are not valid."
                parameters={
                    @ValidationParameter(name="fromDate", value="${startDate}"), 
                    @ValidationParameter(name="toDate",   value="${endDate}")})})
    public String execute(){
        return SUCCESS;
    }