Background
-----------------
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.
Problem
-------------
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).
Solution
------------
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)
Implementation
---------------------
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
Example -
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-
<Rules>
<RuleSetId="1">
<paramA>
<isNull Message ="Parameter A cannot be blank" >true</isNull>
<isNumber>false</isNumber>
<isAlpha>false</isAlpha>
</paramA>
<paramB>
<isNull Message ="Parameter B cannot be blank">true</isNull>
<isNumber Message ="Parameter B is not a number">true</isNumber>
<isAlpha>false</isAlpha>
</paramB>
</RuleSetId>
</Rules>
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.
Regards,
Ashutosh
-
Central Primary Data Validator (18 messages)
- Posted by: Ashutosh Shinde
- Posted on: November 05 2003 01:05 EST
Threaded Messages (18)
- Central Primary Data Validator by Harish Babu on November 06 2003 07:00 EST
- Central Primary Data Validator by Ashutosh Shinde on November 07 2003 03:56 EST
-
Some thing Jakarta Commons Validator by Manish Bellani on November 07 2003 05:15 EST
- Jakarta Commons Validator by Ashutosh Shinde on November 07 2003 06:03 EST
- Validators... by Sean Sullivan on November 10 2003 07:34 EST
-
Some thing Jakarta Commons Validator by Manish Bellani on November 07 2003 05:15 EST
- Central Primary Data Validator by Ashutosh Shinde on November 07 2003 03:56 EST
- validation class also is defined in XML by Yong Zhang on November 08 2003 22:28 EST
- validation class also is defined in XML by Ashutosh Shinde on November 10 2003 01:46 EST
- Sample validator code by Srini Penchikala on November 09 2003 23:04 EST
- Sample validator code by Ashutosh Shinde on November 10 2003 01:52 EST
- Not a pattern by Nils Kilden-Pedersen on November 11 2003 13:58 EST
- Validator is in fact a type! by Michael Schnell on November 14 2003 07:18 EST
- Validator is in fact a type! by Ashutosh Shinde on November 18 2003 23:24 EST
- Jakarta Struts Commons Validator by Abhik Basu on December 04 2003 06:31 EST
- business validation by Suresh R on December 04 2003 11:43 EST
- A Simpler Solution by Peter Schlemowitz on May 19 2004 00:27 EDT
- not "central" or a pattern by bruce goldstein on August 24 2004 07:04 EDT
- Linking request parameters to an process/action by Bolle Kanin on December 23 2004 02:28 EST
- Linking request parameters to an process/action by Bolle Kanin on December 23 2004 02:39 EST
-
Central Primary Data Validator[ Go to top ]
- Posted by: Harish Babu
- Posted on: November 06 2003 07:00 EST
- in response to Ashutosh Shinde
The solution looks simple but when we need to have internationalised messages then the solution should have some thing extra to cater to it -
Central Primary Data Validator[ Go to top ]
- Posted by: Ashutosh Shinde
- Posted on: November 07 2003 03:56 EST
- in response to Harish Babu
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 -
<Rules>
<RuleSetId="1">
<paramA>
<isNull Message ="MSG1" >true</isNull>
<isNumber>false</isNumber>
<isAlpha>false</isAlpha>
</paramA>
<paramB>
<isNull Message ="MSG2">true</isNull>
<isNumber Message ="MSG3">true</isNumber>
<isAlpha>false</isAlpha>
</paramB>
</RuleSetId>
</Rules>
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.
Regards,
Ashutosh -
Some thing Jakarta Commons Validator[ Go to top ]
- Posted by: Manish Bellani
- Posted on: November 07 2003 05:15 EST
- in response to Ashutosh Shinde
Your idea seems to be same as what Jakarta Commons Validator API. Is it, So?
Thanks,
Rajendra Alapty -
Jakarta Commons Validator[ Go to top ]
- Posted by: Ashutosh Shinde
- Posted on: November 07 2003 06:03 EST
- in response to Manish Bellani
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 :) -
Validators...[ Go to top ]
- Posted by: Sean Sullivan
- Posted on: November 10 2003 19:34 EST
- in response to Manish Bellani
Jakarta Commons Validator
http://jakarta.apache.org/commons/validator/
Struts Validator
http://jakarta.apache.org/struts/userGuide/dev_validator.html -
validation class also is defined in XML[ Go to top ]
- Posted by: Yong Zhang
- Posted on: November 08 2003 22:28 EST
- in response to Ashutosh Shinde
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" />
<form name="form-name">
<field name="filed name" validator="validation rule name">
<init-param param-name="value" />
</field>
...
</form>
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). -
validation class also is defined in XML[ Go to top ]
- Posted by: Ashutosh Shinde
- Posted on: November 10 2003 01:46 EST
- in response to Yong Zhang
Hi Yong,
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.
Regards,
Ashutosh -
Sample validator code[ Go to top ]
- Posted by: Srini Penchikala
- Posted on: November 09 2003 23:04 EST
- in response to Ashutosh Shinde
Ashutosh,
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. -
Sample validator code[ Go to top ]
- Posted by: Ashutosh Shinde
- Posted on: November 10 2003 01:52 EST
- in response to Srini Penchikala
Hi Srini,
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.
Regards,
Ashutosh -
Not a pattern[ Go to top ]
- Posted by: Nils Kilden-Pedersen
- Posted on: November 11 2003 13:58 EST
- in response to Ashutosh Shinde
This is not a pattern, but design.
You state:
"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. -
Validator is in fact a type![ Go to top ]
- Posted by: Michael Schnell
- Posted on: November 14 2003 07:18 EST
- in response to Ashutosh Shinde
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.
If there is a need to "copy" this information to Javascript for a "pre-flight" check on the client side then Javascript should be generated out of the Java object. This assures consistency between business object and Javascript. -
Validator is in fact a type![ Go to top ]
- Posted by: Ashutosh Shinde
- Posted on: November 18 2003 23:24 EST
- in response to Michael Schnell
Hi Michael,
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.
Regards,
Ashutosh -
Jakarta Struts Commons Validator[ Go to top ]
- Posted by: Abhik Basu
- Posted on: December 04 2003 06:31 EST
- in response to Ashutosh Shinde
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]..... -
business validation[ Go to top ]
- Posted by: Suresh R
- Posted on: December 04 2003 11:43 EST
- in response to Abhik Basu
there are situations where some business validations need to be performed at the user interface level, for example,
example 1
if field a is "X" and field b is "Y" then accept field "Z" otherwise don't accept field "Z"
example 2
if field "owner" is "xxx" then field "dept" should be from one of his departments. -
A Simpler Solution[ Go to top ]
- Posted by: Peter Schlemowitz
- Posted on: May 19 2004 00:27 EDT
- in response to Ashutosh Shinde
Use a regex expression - handles all cases. -
not "central" or a pattern[ Go to top ]
- Posted by: bruce goldstein
- Posted on: August 24 2004 07:04 EDT
- in response to Ashutosh Shinde
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.
Bruce -
Linking request parameters to an process/action[ Go to top ]
- Posted by: Bolle Kanin
- Posted on: December 23 2004 02:28 EST
- in response to Ashutosh Shinde
Hi,
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:
<ValdationRules>
<Request name="doSomething">
</Request>
</ValdationRules> -
Linking request parameters to an process/action[ Go to top ]
- Posted by: Bolle Kanin
- Posted on: December 23 2004 02:39 EST
- in response to Ashutosh Shinde
Hi,
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):
<ValdationRules>
<Request name="doSomething">
<Param name="param1" type="String" mandatory="true">
<ValidateLength execute="true" min="10" max="128"/>
<ValidateEncoding b64="true" hex="false" uenc="true"/>
...
...
</Param>
<Param name="param2" type="Integer" mandatory="true">
<ValidateLength execute="false"/>
<ValidateEncoding uenc="true"/>
...
...
</Param>
...
</Request>
</ValdationRules>
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.