JavaLite has a validation framework that is somewhat reminiscent of ActiveRecord validation. Unlike ActiveRecord, it can be applied to regular Java classes as well as ActiveJDBC models.

In all cases, the rules are declared inside the classes of objects to be validated using a static blockl (models) or using a constructor (standard classes).

The validation rules in ActiveJDBC are described in a model definition in a declarative way.

Validation Framework principles

Inheritance - based

Unlike other frameworks for validation, the JavaLite Validation framework is based on inherited functionality, which might be limiting in some cases.

Declarative style

The validation rules are provided in a declarative manner, not programmatic in most cases. For example, if you need to validate a presence of a value (that an attribute of an object is not null), simply declare: validatePrecenseOf("first_name"), and the framework will be generating corresponding messages during a validation phase.

Exception - free

The Validation framework, unlike others, will not generate any exceptions, but rather will accumulate validation erros and and make them available for developers, such as:

where first_name is a name of an attribute of a person object.

Validation support for simple classes

If you want to use the validation framework with any simple class, you would inherit a VaslidationSupport class:

List of validators

For more information on the validators, please see: Validators

Model declarations

In order to add any validation, a model will declare a static block at the top of a class definition, and invoke all validation declaration inside this block:

The method Model.validatePresenceOf() takes a vararg of strings, which allows to specify a list of attribute names (column names) in one line of code.

Simple Java classes: Triggering of validation

Here is an example of a non-model Java bean that can use the JavaLite validation:

then, the validation can trigger the same as for a model:

For more examples, you can see the ValidationSpec.

Models: Triggering of validation

The following methods will invoke validation:

  • Call Model.validate() method (will not throw exception)
  • Call Model.save() method (will not throw exception)
  • Call Model.saveIt() method (will throw exception)
  • Call Model.createIt() method (will throw exception)

The semantic difference of save() and saveIt() methods is described on the Record creation page.

If course, you can also just call model.validate() method directly.

Consuming validation messages

After the validation triggered, you can retrieve all messages from a model as a collection:

As you can imagine, it is very easy to write web applications with form validation using this ActiveJDBC.

Usage in a web application (non-ActiveWeb)

This is a pseudo-code of a web application controller where a form was submitted:

In a JSP:

For more information on using validations and conversions in web requests, see here

Customized messages for different attributes

You can call method validatePresenceOf().message() multiple times, providing different attribute names as well as different messages:

Validation of numericality

ActiveJDBC like ActiveRecord also provides other validators, for instance:

Like the validatePresenseOf(), this method also takes in a vararg of strings, which allows to specify a list of attribute names that should have a numeric format.

Validation of numericality with additional properties

When checking numericality of an attribute, you can have a finer control, including specifying that it could be null, providing a range and a custom message. In fact, all validators allow for custom message.

Again, ActiveJDBC is using Fluent Interfaces technique, as in many other places.

Range validator

Besides numeric validation, there is also a specific range validator:

Although you can use either numeric or range validators for range, in some cases range validator will have a more concise syntax than numeric one.

Email validator

The email validator exists to check a proper format of email (it does not check if email actually exists!)

Regular expressions validator

You can probably guess, that the email validator is a special case of a regular expression validator:

This validator provides enough freedom to developers who know regular expressions well :)

Custom validators

If all else fails, and ActiveJDBC does not provide a validator you want, you can extend a ValidatorAdapter class:

or better yet, ValidatorAdapter:

Once you have a custom validation, you can register it with a model like this:

Another way to register is outside your model class:

after a validation, you can retrieve an error like this:

Validators are executed during validation in the order they were added to the model. The validate() method is called from save() and saveIt()

Resource bundles

ActiveJDBC provides stock messages (one for each validator), which may not be appropriate for all projects. For instance, validatePresenseOf() provides a simple message value is missing. In order to customize these messages, the framework provides a DSL-ish like facility:

where name.missing is a key from a resource bundle activejdbc_messages.

After a validation process, if there are errors, they are accessible via the p.errors() method, and a specific validation error message is accessed using an attribute name as a message key:

..or you can use the Errors object returned from errors() method as a Map and process it generically (as is usually the case for web applications).

Parametric validation messages

In some cases, you will need to parametrize messages coming from a resource bundle. For instance, in a file activejdbc_messages.properties you would have an entry:

temperature.outside.limits = Temperature is outside acceptable limits, while it needs to be between {0} and {1}

You might have a model defined like this:

You will then create an instance of Temperature, set the values and validate in a code pattern similar to this;

Split parameters for validation messages

In some cases you know parameter values when declaring a model, but some other parameters are only known in the context where validation is actually used. In this case, you can split parameters between the declaration (static context) and calling for messages (dynamic context).

Resource bundle:

temperature.outside.limits = Temperature is outside acceptable limits, while it needs to be between {0} and {1} for user: {2}

Model definition:

As you can see, the message calls for three parameters, but the validator can only set two. At the time of Model definition, the user is not known. However, the user can be provided when the validation fails, and an application calls for an error message:

The getter method for Errors class has this signature: get(String attributeName, Object ... params), which allows to supply more than one parameter.

The one rule you have to keep in mind, is that static parameters will be indexed from zero, and dynamic parameters will be appended to static. As in this case, the user name is placed in the message at index {2}.

Internationalization of validation messages (I18N)

In cases where there is a need for internationalization of messages, this is easy to accomplish by providing a locale instance to the errors() method. But first, you will need to create these messages. ActiveJDBC uses a resource bundle activejdbc_messages. This means:

  • activejdbc_messages.properties - default locale bundle
  • activejdbc_messages_de_DE.properties - German/Germany bundle
  • etc.

As usual in Java you will need to create a bundle for each locale. If you need a localized message during runtime, all you need it to provide a locale to the errors() method of a model. Building on the example above with temperature, the German local bundle file will have this:

temperature.outside.limits = Die Temperatur liegt außerhalb akzeptabler Grenzen, während es sein muss zwischen {0} und {1}

At run time, the message will be printed in German if a locale provided is German:


How to comment

The comment section below is to discuss documentation on this page.

If you have an issue, or discover bug, please follow instructions on the Support page