For applications that accept information via the external interfaces (web or otherwise), it is critical to check the validity of the data that is passed to it by the client.
The data validation is driven by business logic and typically comprises of the checks (referred as Primary validations) as mentioned below-
1. Null value check - Whether the data is null or not.
2. Data type checks - Whether the data is numeric, alpabetic or alpha-numeric
3. Data length checks - Whether the size of the data received matches the requirement
4. Special Characters checks - Whether the data carries special characters like "!", "#", "^" etc. For example, it is obviously wrong for the name field to carry "#" in it
These checks are defined by the application logic and are certainly not limited to the ones defined above.
In case of applications which involve the browsers, such validations are enforced by the Java Script. The Java Script executes on the Client side and ensures that invalid data is not passed to the server, to eliminate unnecessary processing of invalid data at the server side.
However, there is an apparent problem in enforcing the rules in the following cases -
1. In case of non-browser based clients, it is not possible to use Java Script for enforcing the rules. An example is a client (JSP/Servlet/ASP/PERL etc) who opens a URL Connection to the server and posts the parameters
2. Also, with Java Script, there is a problem as the web customer can turn off the Java Script execution on the browser.
The above 2 points imply that the data validations need to be executed on the server also.
The typical manner in which the above requirement is handled is as follows -
1. Write a helper class with methods like
boolean isNull(String astrXXX)
boolean isNumber(String astrXXX)
boolean isAlphabetic(String astrXXX)
boolean isEmailValid(String astrXXX)
These methods validate the data that is passed.
2) The JSP /Servlet invokes the methods of the helper class based on the paramater that needs to be validated. Very frequently, a single paramater may result in multiple method invocations on the helper. For example, a parameter may be required to be "not null" and also numeric. Thus, the methods isNull(String astrXXX) and isNumber(String astrXXX) willbe invoked.
3) Based on the value returned by the method, the JSP/Servlet proceeds with the flow as per the business requirement.
However, there are certain problems in the above process -
1. Any change in the parameter check results in the change in the code. The clients of the helper class need to be changed to incorporate the new logic.
2. The JSP/Servlet needs to understand the business data validation rules. Each JSP/Sevlet must know the data that needs to be validated and the validation rules that need to be applied to the data. Thus, indirectly some amount of business logic seeps into the User Interface layer.
3. A single parameter typically results in multiple calls on the Helper class. This results in the cluttering of the JSP/Servlet or the Action Class(if used).
To resolve the above problems -
Create a Primary Validator component which -
a. acts as a centralized point for primary validations for the application
b. is driven by configurable rule set that defines the validation logic and which is de-coupled from the User Interface layer
c. provides a single interface for for all the validations that need to be executed, so as to reduce the method calls (and hence the clutter)
1) An XML which contains the validation rules needs to be defined. Each set of validation rules is marked by an unique identifier. One JSP/Servlet may be associated with multiple such rule sets
Consider a HTML which contains the fields A,B and C
A and B need to be checked for null values. They cannot have null values
B also needs to be checked for numeric data.
The above requirements would result in a single rule set -
The XML would look something like this-
<isNull Message ="Parameter A cannot be blank" >true</isNull>
<isNull Message ="Parameter B cannot be blank">true</isNull>
<isNumber Message ="Parameter B is not a number">true</isNumber>
This is a very simplistic XML and certainly needs to be enhanced further.
2) A Primary Validator class needs to load the XML in memory in the static block.
3) The Validator provides an interface which accepts the HttpServletRequest and the Rule Set Id from the caller. Thus the calls from the JSP/Servlets can be reduced
The caller will call the function, say validateData(HttpServletRequest oReq, String astrId).
4) Based on the Id passed, the Validator will sequentially loop through the different parameters defined in the XML and then apply the validation rules as defined. The Validator would throw an application exception with the message as defined in the XML for the check. This message can be displayed on the browser.
Please do provide your comments and suggestions.
The solution looks simple but when we need to have internationalised messages then the solution should have some thing extra to cater to it
I can currently think of one way by which the internationalization issue can be addressed -
1. Introduce an ID for each message that can be displayed. So going by the same example which I posted -
<isNull Message ="MSG1" >true</isNull>
<isNull Message ="MSG2">true</isNull>
<isNumber Message ="MSG3">true</isNumber>
2. In a properties files set the locale along with the message ID against the message.
So for english locale the properties file will carry -
en.MSG1 = Parameter A cannot be blank
en.MSG2 = Parameter B cannot be blank
en.MSG3 = Parameter B is not a number
Similarly, say for french
fr.MSG1 = Le paramètre A ne peut pas être blanc
fr.MSG2 = Le paramètre B ne peut pas être blanc
fr.MSG3 = Le paramètre B n'est pas un nombre
and so on.
3 A small change will be required in the interface validateData(HttpServletRequest oReq, String astrId) which will now accept the locale of the user. The interface will now be modified to validateData(HttpServletRequest oReq, String astrId, String astrLocale).
4 A helper class will read the properties file and then based on the message id and the locale passed to it will return the message back.
I hope this should address the issue of localization.
Your idea seems to be same as what Jakarta Commons Validator API. Is it, So?
The pattern which I have posted tries to address the issues which are generally faced when developing the User Interface like cluttering, introduction of Business Logic etc. The post tries to captue the essence of the problem and attempts to provide a solution to the same.
Whether Jakarta or anything else uses a concept of a centralized validator component/s is something that I am not aware of. If it does and it does well, then I would be more than happy since it would imply that the pattern does work :)
I used a similar method as yours. but I define the validator in XML file like this:
<validator name="validation rule name" class="class name" />
<field name="filed name" validator="validation rule name">
<init-param param-name="value" />
All validators have same interface, so server don't need to know which class will be used. And concrete validator implement SetParamName methods to get parameters' value from XML files (for instance, the range of a number field).
Thanks for your reply.
I think adding the Validator in the XML does make sense since it gives the user the option to segregate the logic further into various business classes. Also, since the Interface remains intact and simple, I think your idea will add value to the implementation.
I was wondering if you have any sample code of the validator class. In my current project, we have a requirement to process the validation on the JSP container (Tomcat) and I need to reuse the validation rules already defined to be used on the EJB application server. Could you post the sample java code you used in your validation framework.
I have not developed any code for the pattern as yet. I thought that it would make sense to wait for the opinions from the experts on the pattern before I start the code.
Sorry to dissapoint you on that front.
This is not a pattern, but design.
"Whether Jakarta or anything else uses a concept of a centralized validator component/s is something that I am not aware of. If it does and it does well, then I would be more than happy since it would imply that the pattern does work."
That would imply that the *design* works. A pattern *always* work, because its based on established principles that have been proven to work, time and time again.
Isn't all this "Validator" stuff a bit weird?
In fact all those checks mentioned (length, min/max, null, pattern, special characters) should be part of the data type!
If you want a "String" to have a min or max length there should be a "RestrictedLengthString" type. It's just the same with subrange types:
Let's say you have an int variable that can have values "1", "3" or "5" - This is just a special enumeration type.
How would the application identify whether a parameter received should be checked against the "RestrictedLengthString" or the special enumeration type for integers.
There needs to be a controller which indicates the checks to be applied on the data received. And hence the "Validator".
Also, irrespective of where the Java Script is generated, the efficacy of the Java Script is always doubtful once it reaches the client.
u can do all these stuffs with Struts framework..... U can even do all these simple validation pagewise [an application may need several pages to navigate before completing the entire transaction].....
there are situations where some business validations need to be performed at the user interface level, for example,
if field a is "X" and field b is "Y" then accept field "Z" otherwise don't accept field "Z"
if field "owner" is "xxx" then field "dept" should be from one of his departments.
Use a regex expression - handles all cases.
While the concept is nice, it is not a pattern. A pattern would be something like "always validate incoming info" or something. Also you are not centrally validating anything but expressing more of a best practice as your ideas can be easily avoided by developers on a project.
I have validation built into my domain model. This is always called via the InstanceCallbacks interface in JDO (the jdoPreStore method). Thus before any domain objects are written to my database they will be validated. This method is "central" because it is ALWAYS called before a store operation. Developers CAN NOT avoid it.
Also, please do not reimplement the wheel. Jakarta has a million and one implementations and their validator has been around for a while. Before posting a pattern its a good idea to check their for an already existing implementation. It is just confusing to newbies to see all these patterns out their when they have already been done.
It is interesting reading about your design and the funny thing is that i had the same design in mind a couple of months ago. And yes, i implemented a RequestValidator :) The only thing that is different between my design and yours is that i found it necessary to define (link) which request parameters belonged to a request. So, my xml hot to look like this:
It is interesting reading about your design and the funny thing is that i had the same design in mind a couple of months ago. And yes, i implemented a RequestValidator :) The only thing that is different between my design and yours is that i found it necessary to define (link) which request parameters belonged to a request. So, my xml got to look like this (the example below is just the core xml elements):
<Param name="param1" type="String" mandatory="true">
<ValidateLength execute="true" min="10" max="128"/>
<ValidateEncoding b64="true" hex="false" uenc="true"/>
<Param name="param2" type="Integer" mandatory="true">
The RequestValidator is today running in many applications (webbased and others) and it is a good idea. It is SIMPLE (core java), it is generic, it is fast and it works.
Good luck and think about linking parameters to a process (workflow) or action, it is very usefull.