Validation explained
Stuts2 uses XWork's validation framework internally.
It allows you to validate Models and Actions using a set of specialised (field)validators, grouped together in an xml file named YourModel-validation.xml or ActionName-validation (and, in the case of the alias, ActionName-alias-validation.xml).
Since we only want to validate the crud action, we create a file EmployeeAction-crud-validation.xml and place it in our classpath (mostly next to our compiled Action class).
A very important reminder: validation is once again done by an
interceptor, so it should be in your stack. Even more important,
validators 'query your Action/Model' and NOT your request! Keep this in
mind at all times.
With that out of the way, let's analyze this snippet: there are two types of validators: field validators and general validators. We start by analyzing the field employee.firstName - so this means: we will analyze the result from the invocation of getEmployee().getFirstName() on our Action, not the request parameter named employee.firstName!
Field validators will not validate input fields - they are named field validators because they will automatically mark the input field in your form with the validation error, whereas normal validators would create actionErrors.
First we apply a
The employee.lastName validation is exactly the same as the firstName. The only difference is in the validation of the age property.
We use in fact 2 validators: a 'required' one, which will make sure that our age is in fact set, and not null, and another one that will check the range to make sure our employee is between 18 and 65 years old. If course, if the first validator fails, we shouldn't continue processing, so that's why we can specify the short-circuit attribute. If a validator short-cicuits the validation, validation is failed and skips the current (field) validator.
The "int" validator takes 2 optional parameters: min and max, who can be set by providing two simple param tags (most items in S2 can be configured that way). This way, we ensure validation to be loosely coupled with our code and do not require re-compilation.
Of course, you should also be able to i18n'ize your error messages, so that's why we providing a <message key="my_key"/> - if you prefer otherwise, you can always add a hardcoded text as a child element of the message tags.
It does not stop there. The text you pass, be it hardcoded or a looked-up value, can in fact contain OGNL expressions as well !
Take a look at the value we get back from the 'errors.required.age.limit'-key:
And guess what: min and max are indeed the two parameters we just set
before ! Using OGNL expressions you can retrieve whatever you want from
your validator/action/context, giving you really nice error messages
(we like nice error messages).
In fact, you can not only use these expressions in your error messages, but you can even set the min and max parameters dynamically. Different types of employees could have different age requirements - OGNL and polymorphy to the rescue !
It allows you to validate Models and Actions using a set of specialised (field)validators, grouped together in an xml file named YourModel-validation.xml or ActionName-validation (and, in the case of the alias, ActionName-alias-validation.xml).
Since we only want to validate the crud action, we create a file EmployeeAction-crud-validation.xml and place it in our classpath (mostly next to our compiled Action class).
<validators> <field name="employee.firstName"> <field-validator type="requiredstring"> <message key="errors.required.firstname"/> </field-validator> </field> <field name="employee.lastName"> <field-validator type="requiredstring"> <message key="errors.required.lastname"/> </field-validator> </field> <field name="employee.age"> <field-validator type="required" short-circuit="true"> <message key="errors.required.age"/> </field-validator> <field-validator type="int"> <param name="min">18</param> <param name="max">65</param> <message key="errors.required.age.limit"/> </field-validator> </field></validators> |
With that out of the way, let's analyze this snippet: there are two types of validators: field validators and general validators. We start by analyzing the field employee.firstName - so this means: we will analyze the result from the invocation of getEmployee().getFirstName() on our Action, not the request parameter named employee.firstName!
Field validators will not validate input fields - they are named field validators because they will automatically mark the input field in your form with the validation error, whereas normal validators would create actionErrors.
First we apply a
requiredstring validator to the
getEmployee().getFirstName() return value. There are quite a few
validators, ranging from requiredstring, required, intrange,
emailaddress, url, .. etc. Writing your own validator is not hard, and
it can be reused easily. Here we use the requiredstring, which does 2
checks:- check the availabilty of the string (!= null)
- check the length of the string to be > 0
The employee.lastName validation is exactly the same as the firstName. The only difference is in the validation of the age property.
We use in fact 2 validators: a 'required' one, which will make sure that our age is in fact set, and not null, and another one that will check the range to make sure our employee is between 18 and 65 years old. If course, if the first validator fails, we shouldn't continue processing, so that's why we can specify the short-circuit attribute. If a validator short-cicuits the validation, validation is failed and skips the current (field) validator.
The "int" validator takes 2 optional parameters: min and max, who can be set by providing two simple param tags (most items in S2 can be configured that way). This way, we ensure validation to be loosely coupled with our code and do not require re-compilation.
Of course, you should also be able to i18n'ize your error messages, so that's why we providing a <message key="my_key"/> - if you prefer otherwise, you can always add a hardcoded text as a child element of the message tags.
It does not stop there. The text you pass, be it hardcoded or a looked-up value, can in fact contain OGNL expressions as well !
Take a look at the value we get back from the 'errors.required.age.limit'-key:
errors.required.age.limit=Please provide an age between ${min} and ${max}. |
In fact, you can not only use these expressions in your error messages, but you can even set the min and max parameters dynamically. Different types of employees could have different age requirements - OGNL and polymorphy to the rescue !