Fork me on GitHub

Integration with Apache Commons Validator

Commons Validator is an input validation component devised (originally) by David Winterfeldt as an addon for the Struts framework. It’s functionality has since been split so that validator can serve as the basis for a independent component and is now part of Jakarta Commons.

Struts users use the html:javascript tag library to have Validator generate validation javascript for client side validation. The downside of this approach is that the javascript is generated inline, so the browser will not cache it. Also, care must be taken to avoid the “static” javascript (the reusable validation logic) being generated on every page.

With Jawr it is possible to have the commons validator scripts minified and compressed, and they can also be included as part of a bundle. This way, the static javascript could be included in a bundle with other infrastructure code such as libraries (Prototype.js, JQuery or others). Also, several related form validations can be bundled together, with the added benefit of minification and browser caching.

Currently, using Jawr with Validator has a couple of limitations:

  • Multipage validators are not supported.
  • Form validator generation is still in beta stage. It is usable but you should test each form since bugs may appear.

These caveats can be bypassed by using the html:javascript tag in pages that require it, since both approaches can coexist without interference. The static javascript however can be used normally and by itself will be a welcome improvement to any project using the Validator.

How to map Validator scripts

The first thing required to use the Validator with Jawr is to create an entry in the Jawr properties file defining the paths to Validator config files. The paths are the same used to define any Validator instance. This entry can have any name you want, as you will later use this name to define the mappings.

For instance, if the Validator plugin configuration in struts were as follows:

  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" value="/org/apache/struts/validator/validator-rules-compressed.xml,
                                              /WEB-INF/validator/validation.xml" />
      <set-property property="stopOnFirstError" value="true" />
  </plug-in>

The config param would look like this:

  jawr.validator.config=/org/apache/struts/validator/validator-rules-compressed.xml,/WEB-INF/validator/validation.xml

This variable defines a Validator config instance. If you have several modules with a different validator each, you would add a similar entry for each one. This is not needed if you will only use the static javascript generation and all your modules have the same javascript validators.

The next thing you do is to add the mappings. The syntax for a mapping is the following:

  acv:mapping1|mapping2([config param]|[messages namespace]|[stop on errors])

The mapping starts with acv: followed by the mappings separated by a pipe character. The mappings are form names as defined in the Validator config files, or _static to get the static javascript.

After the mappings, within parentheses you write the config param name (the one you defined previously). The ‘messages namespace’ and ‘stop on errors’ params are optional and are discussed below. Here is a simple mapping sample:

jawr.validator.config=/org/apache/struts/validator/validator-rules-compressed.xml,/WEB-INF/validator/validation.xml
jawr.js.bundle.global.id=/bundles/global.js
jawr.js.bundle.global.mappings=acv:_static|loginForm(jawr.validator.config)

This creates a bundle that contains the static Validator scripts and the validator for the form named ‘loginForm’. Note that this bundle may contain other mappings, so you can combine the Validator scripts with any other javascript in your project. For instance, you could combine Prototype.js, scriptaculous and the static validations:

jawr.js.bundle.global.id=/bundles/global.js
jawr.js.bundle.global.mappings=/js/protaculous/**, acv:_static(jawr.validator.config)

i18n

The commons validator generates locale specific messages. Normally, what it does is to use the HTTPServletRequest coming to a JSP to determine the required locale and it generates javascript using a ResourceBundle which contains the localized messages for validation. For instance:

errors.required={0} is required.
errors.minlength={0} can not be less than {1} characters.
errors.maxlength={0} can not be greater than {1} characters.
errors.invalid={0} is invalid.

As opposed to this, Jawr generates all the bundles when the application starts up (thus saving some overhead compared to the former approach). As a consequence, the way locale specific messages are resolved needs to be different. Fortunately, Jawr has a means to transfer i18n messages to javascript, which the validator uses. Therefore, you need some familiarity with the i18n messages generator to use the Validator feature. Take a look and return here if you don’t know about it.

So additional to the Validator scripts, you need also an i18n script with the messages required by the validator. To do that, you create a mapping to the ResourceBundle that contains said messages:

jawr.js.bundle.global.mappings=messages:org.apache.struts.webapp.validator.MessageResources

You can of course organize the way to import the scripts as you wish. You can combine the messages from the validator with your own, or you can create a bundle with both the messages and the validators:

jawr.js.bundle.global.mappings=messages:org.apache.struts.webapp.validator.MessageResources,acv:_static|loginForm(jawr.validator)

As stated in the i18n messages generator documentation, the namespace for the messages can be configured, with ‘messages’ being the default. If for whatever reason you change this namespace, you will need to specify it in the validator mapping too, like this:

jawr.js.bundle.msg.mappings=messages:org.apache.struts.webapp.validator.MessageResources(mynamespace)
jawr.js.bundle.global.mappings=acv:_static|loginForm(jawr.validator|mynamespace)

Stop on errors

There are to ways to show messages to the user with the Validator. If ‘stop on errors’ is set to true, then Validator will display one alert message with the first category of errors encountered. For instance, if you have a mandatory field and a date validation, only the mandatory message is displayed. If stop on errors is set to false, the user gets two alert messages, one for the mandatory field and other for the date field.

When used with Jawr, this value defaults to true (only one alert message). If you wish to change this behavior, you add a third parameter to the mapping:

jawr.js.bundle.global.mappings=acv:_static|loginForm(jawr.validator|messages|false)

Note that when using this parameter you must define the namespace. If you didn’t change it the i18n bundle, just set it to the default value ‘messages’ as in the example.