Details
Description
For all of those who are tired of requiredif and validWhen - here is the
Expression Language Field Validator.
What it does?
It gives the developer the power of EL to do a validation. This implementation
also provides access to most EL scopes including request, session, and
application scope.
No more "only two items may be joined with and or or "
Implementation notes:
- uses JEXL (http://jakarta.apache.org/commons/jexl/)
- uses EnumeratedMap from standard taglibs (if someone does not like this
dependency - Map can be copied over to struts package, or became the internal class)
Things added:
- ELValidator - class that provides validate method
- PageContext implementation (reused MockPageContext)
Two classes - simple and beautiful.
1. Features:
1.1 Operators
(http://jakarta.apache.org/commons/jexl/reference/syntax.html#Functions):
- Arithmetic: +, - (binary), /, div (int division), % and mod, -(unary)
- Logical: and, &&, or, ||, not, !
- Relational: ==, eq, !=, ne, <, lt, >, gt, <=, ge, >=, le.
- Array access: arr1[0], arr1.0
- Empty()
- Size()
Notes:
- Avoid the '&', '<', '>' in validation.xml
- escape them: & > < or use 'and' 'lt' 'gt'.
- No ternary operator A?B:C, workaround:
- if A return B else C -> can be translated as "(A and B) or (!A and C)"
- if A return B -> can be translated as "(B or !A)"
1.2 Implicit Objects
- pageContext provides access to:
- servletContext
- session
- request
- response, servletConfig (no access to response and ServletConfig)
- param - maps a request parameter name to a single value
- paramValues - maps a request parameter name to an array of values
- cookie - maps a cookie name to a single cookie
- header - maps a request header name to a single value
- headerValues - maps a request header name to an array of values
- initParam - maps a context initialization parameter name to a single value
1.3 Scoped variables:
- pageScope - maps page-scoped variable names to their values
- requestScope - maps request-scoped variable names to their values
- sessionScope - maps session-scoped variable names to their values
- applicationScope - maps application-scoped variable names to their values
1.4 Additional Objects
- form - form bean, added as a place holder for form variables
- arrayUtils - "instance" of commons ArrayUtils
allows expressions like:
arrayUtils.contains(paramValues.topic, "spring') - stringUtils - "instance" of commons StringUtils
- var - contains variables defined for this field in the validaton definitions
- vars - contains variables defined for this field in validator definitions,
each one is string array, elements should be coma separated
2. Definition (this step is not needed since the
jakarta-struts/conf/share/validator-rules.xml was updated)
Validator definition in global section of validation.xml:
<validator name="EL"
classname=" org.apache.struts.validator.ELValidator"
method="validateEL"
methodParams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionMessages,
javax.servlet.http.HttpServletRequest,
javax.servlet.ServletContext"
msg=" errors.required"/>
3. Examples
3.1. Company field is required for everyone except CSR and Admin.
<field property="company" depends="EL" page="1">
<var><var-name>EL</var-name>
<var-value>
(sessionScope.currentUser != null
and (
sessionScope.currentUser.userCSR
or sessionScope.currentUser.userAdmin
)
) or !empty form.company
</var-value></var>
<arg0 key="company.displayname"/>
</field>
Note: Try to write it with the validWhen
3.2. Only published status is allowed.
<field property= "status" depends="EL" page="1">
<var><var-name>allowedStatus</var-name>
<var-value>published</var-value></var>
<var><var-name>EL</var-name>
<var-value>
form.status == var.allowedStatus
</var-value></var>
<arg0 key="id.displayname"/>
</field>
3.3. "id" required only for edit, delete and store methods (RequestDispatcher).
<field property= "id" depends="EL" page="1">
<var><var-name>methods</var-name>
<var-value>editForm,insert,update,delete</var-value></var>
<var><var-name>EL</var-name>
<var-value>
!empty form.id
or !arrayUtils.contains(vars.methods, param.email)
</var-value></var>
<arg0 key="id.displayname"/>
</field>
In my opinion it makes validation a way easier to write and to read
Please fell free to post comments. I hope you will enjoy it.
Lukasz Racon