Browse DevX
Sign up for e-mail newsletters from DevX


Extend the JDK Classes with Jakarta Commons, Part I : Page 2

Explore the components in the Jakarta Commons set of reusable classes and you'll be convinced that most of them should be part of the JDK. Learn which ones you should use in your projects.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Steps to Use the Commons Validator
Take the following steps to make the most of the Commons Validator component:
  1. Write or reuse a POJO validation class
    In order to use Commons Validator, the first step is to write classes that will perform the validations for a set of data. For this example, I wrote the class GenericBeanValidator to validate 'proposedLoginName' and 'mailAddress'. The following is the GenericBeanValidator class structure:

    public class GenericBeanValidator { public static boolean validateRequired(Object bean, Field field) { String value = ValidatorUtils.getValueAsString(bean, field.getProperty()); return !GenericValidator.isBlankOrNull(value); } public static boolean validateEmail(Object bean, Field field) { String value = ValidatorUtils.getValueAsString(bean, field.getProperty()); return GenericValidator.isEmail(value); } }

    The validation class doesn't adhere to any API, just a simple POJO class, which you can unit test easily. I use the ValidatorUtils and GenericValidator classes, which are part of Commons Validator, to achieve this goal. The getValueAsString method introspects the Registration bean to fetch the value for a property and returns a string. The GenericBeanValidator class acts like a wrapper around GenericValidator to validate a bean. The GenericValidator class contains many other utility methods to perform various validations. (Refer to the javadoc to make the best use of Commons Validator.)

  2. Define the mapping XML file
    The next step is to define a XML file that declares the validation classes (like the one written in the previous step) and wires them up to the beans, which need to be validated. The Validator engine will consume the XML file (more about this shortly). The registration.xml file for the example looks as follows:

    <form-validation> <global> <validator name="required" classname="in.co.narayanan.commons.validator.GenericBeanValidator" method="validateRequired" methodParams="java.lang.Object, org.apache.commons.validator.Field" msg="required.field"/> <validator name="email" classname="in.co.narayanan.commons.validator.GenericBeanValidator" method="validateEmail" methodParams="java.lang.Object, org.apache.commons.validator.Field" msg="invalid.email"/> </global> <formset> <form name="userRegistration"> <field property="proposedLoginName" depends="required"> <arg0 key="userRegistration.proposedLoginName.displayname"/> </field> <field property="mailAddress" depends="email"> <arg0 key="userRegistration.mailAddress.displayname"/> </field> </form> </formset> </form-validation>

    The validation classes need to be declared in the <validation> tag. Some of the key properties are logical name, class name, method name, method arguments, and message key, which will be used to fetch an error message if a validation fails. A couple of entries are defined for this example to validate the 'proposedLoginName' and 'mailAddress'.

    The <form> tag is used to map a <validator> definition to a Java Bean property. The <arg0> tag in this example is used to fetch the externalized field name of a Java Bean property. This is useful when displaying a locale-specific displayable field name to the user. The displayable field names and error messages are externalized and available in the file applicationResource.properties. Any number of <argX> tags can appear in a <field> definition.

  3. Initialize and execute the Validator
    When the Commons Validator engine is executed, it checks whether the XML file mapping has defined a validation for a property. If so, it invokes respective validation class methods by passing the necessary arguments. This process repeats for all the properties and the results accumulate along with the error messages. (You will see how to process the results later.)

    The following is a code snippet from the ValidatorEngine class, which the SubmitCommand uses:

    InputStream definitionStream = reg.getClass().getResourceAsStream(definitionXml); .... resources = new ValidatorResources(definitionStream); .... Validator validator = new Validator(resources, Registration.NAME); validator.setParameter(Validator.BEAN_PARAM, reg); .... results = validator.validate(); .... return parseResults(formName, reg, results, resources);

    The ValidationResources class represents the definitions in the XML file. You initialize this class by passing the definitionXml stream and passing the instance to the Validator, along with the name of the bean that needs to be validated. Additional parameters, which a validation class would require, can be passed to the Validator using the setParameter method. Remember, the validateXXXX methods in the GenericBeanValidator class had two arguments: java.lang.Object and org.apache.commons.validator.Field. When executed, the Validator will pass the instance of the bean for the first parameter and the respective field reference for the other.

    You might be wondering how the Validator would pass the reference of some other object (e.g., the HttpServletRequest object) to a validation method. The answer is by calling the setParameter method of the Validator with a fully qualified class name and the reference to the instance of the HttpServletRequest class. The validate method in the Validator can be called to initiate the validations.

  4. Process the results
    The Validator returns an instance of ValidatorResults upon execution. The instance holds all the information about the validations run. The visual structure of the results looks like this:

    [ [property1] [action1] [action2] [property2] [action1] ]

    The results for every bean property are attached in the form of ValidatorAction instances. You begin to iterate over the properties and determine whether a validation succeeded or failed by calling the isValid method in the ValidatorResult class with the action name as a parameter. You'll find the complete parsing logic in the parseResults method of the ValidatorEngine class.

  5. Alternative Uses
    The example has experimented with Commons Validator to validate user input backed by a Java Bean, but you can use it in numerous applications to reap the benefits of modular design, higher productivity, and easier maintenance. The following are some of the possible uses:
    • As a set of validations to apply in a purchase order submitted in XML format to the Web Service layer
    • Validating the state of a class in an application at any given point in time (Appropriate exceptions can be thrown if a class state is not as expected to fulfill a request.)
    • Monitoring an application along with JMX
    • In a rule engine implemented totally in Java (The validation classes would be treated as individual rules to act upon a domain object in a complex business application.)

    This framework also includes a few JavaScript functions to perform client-side validations in a Web application, such as email, URL, etc.

Thanks for your registration, follow us on our social networks to keep up-to-date