Apache MyFaces Extensions Validator

0
108
13 min read

Setting up ExtVal

As with all other libraries, we start by downloading ExtVal and installing it in our project. As with many other JSF libraries, the ExtVal project has different branches for JSF 1.1 and 1.2. The first two digits of ExtVal’s version number are the JSF version they are made for. So ExtVal 1.1.x is the xth version of ExtVal for JSF 1.1, whereas ExtVal 1.2.x is the xth version for JSF 1.2. Versions of ExtVal are not released very often. At the time of writing this article, only two official releases have been published for each branch. According to the lead developer of ExtVal, a third release (1.1.3 and 1.2.3) is in the works for both branches, as well as a first release from the new JSF 2.0 branch.

Apart from stable releases, ExtVal offers snapshot builds that are created on a regular basis. The snapshots are created manually, which gives some guarantees about the quality compared to automatically-created daily releases. No snapshots with major bugs will be created. According to the lead developer of ExtVal, the snapshot builds have “milestone quality”.

Because of some issues and limitations in ExtVal 1.2.2, a snapshot build of ExtVal 1.2.3 was used while writing this article. A stable release of ExtVal 1.2.3 is expected to be available soon after the publishing date of this article. Stable releases can be downloaded from the ExtVal download site at http://myfaces.apache.org/extensions/validator/download.html. The downloaded ZIP file will contain all of the ExtVal modules, as listed in the next table. Note that more modules may be added to ExtVal in future releases. It is also possible that additional support modules will be provided by others. For example, a JSF component project may create a support module to get the most out of its components with ExtVal.

Regarding component support modules, it is also worth mentioning the “Sandbox 890” project, which provides proof of concept implementations of support modules for some non-MyFaces component libraries. Currently, proofs of concept are available for IceFaces, PrimeFaces, RichFaces, and OpenFaces. The source code for the proofs of concept can be found at http://myfaces.apache.org/extensions/validator/download.html. Ready-to-use JARs can be downloaded from http://code.google.com/p/os890-m2-repository/source/browse/#svn/trunk/sandbox890/sandbox890/extensions/validator/component-support-modules.

Library

Description

myfaces-extval-core-1.2.x.jar

The core of ExtVal. This library should be added to the project in all cases.

myfaces-extval-property-validation-1.2.x.jar

Extension module that adds several custom ExtVal annotations that we can use in our Model layer.

myfaces-extval-generic-support-1.2.x.jar

Extension module for generic JSF component support. This library should be added to the project in almost all cases. There are two cases when we don’t need this generic support library, which are as follows:

  • If we’re using a support library for a specific component library, such as the Trinidad support module mentioned in the following row in this table
  • If the component library we’re using is 100% compliant with the JSF specification, which is almost never the case

If no specific support module is in use, and it is unclear if the generic module is needed, it is safe to add it anyway. It is also a good idea to take a look at the Tested Compatibility section on the ExtVal wiki at http://wiki.apache.org/myfaces/Extensions/Validator/.

myfaces-extval-trinidad-support-1.2.x.jar

Extension module that supports the MyFaces Trinidad JSF components. If we use this one, we don’t need the “generic support” module. The Trinidad support module will make use of Trinidad’s client-side validation options where possible. So we get client-side validation based on annotations in our Model with no extra effort.

myfaces-extval-bean-validation-1.2.x.jar

Extension module that adds support for Bean Validation (JSR 303) annotations. This module will be available from the third release of ExtVal (*.*.3).

Snapshot builds of ExtVal can be downloaded from ExtVal’s Maven snapshot repository, which can be found at http://people.apache.org/maven-snapshot-repository/org/apache/myfaces/extensions/validator/. In the case of snapshot builds, no single ZIP file is available, and each module has to be downloaded separately as a JAR file. Note that if Maven is used, there is no need to manually download the snapshots. In that case, we only have to change the version number in the pom.xml file to a snapshot version number, and Maven will automatically download the latest snapshot. The following table lists the URLs within the Maven repository from where the modules can be downloaded:

Module

URL

Core

myfaces-extval-core/

Property validation

validation-modules/myfaces-extval-property-validation/

Generic support

component-support-modules/myfaces-extval-generic-support/

Trinidad support

component-support-modules/myfaces-extval-trinidad-support/

Bean validation (JSR 303)

validation-modules/myfaces-extval-bean-validation/

URLs in this table are relative to the URL of the Maven repository that we just saw. After each URL, 1.2.x-SNAPSHOT/ has to be appended, where 1.2.x has to be replaced by the appropriate version number.

Once we’ve finished downloading, we can start adding the JARs to our project. ExtVal differs in one thing from other libraries—it needs to access our Model and View project. So we have to add the ExtVal libraries to the lib directory of the EAR, instead of the WAR or the JAR with the entities. Some libraries that ExtVal uses have to be moved there as well. If we don’t do this, we’ll end up with all sorts of weird exceptions related to class-loading errors.

Libraries that are added to the lib directory of an EAR are automatically available to all contained WAR and JAR files. However, depending on the IDE and build system that we are using, we may have to take some additional steps to be able to build the WAR and JAR with dependencies to the libraries in the EAR’s lib directory.

Apache MyFaces 1.2 Web Application Development

This image shows a simplified structure of the EAR with ExtVal’s libraries added to it. Note that the MyFaces ExtVal and dependencies node in the image actually represents multiple JAR files. It is important to verify that none of the libraries that are in the lib directory of the EAR are included in either the WAR or the entities JAR. Otherwise, we could still encounter class-loading conflicts. The following table lists all of the libraries that have to be moved into the EAR to avoid these class-loading conflicts:

Library

Explanation

myfaces-extval-*.jar

Of course, all of the needed ExtVal JARs should be in the EAR.

asm-1.5.x.jar, cglib-2.x_y.jar

These are libraries that ExtVal depends on. They are bundled with the ExtVal download. They’re not bundled with snapshot releases.

jsf-facelets.jar

We’re using Facelets, so ExtVal has to use it to add validations within our Facelets pages. So if we didn’t use Facelets, this one would not be needed.

myfaces-api-1.2.*, myfaces-impl-1.2.*

We’re using MyFaces Core as JSF implementation. ExtVal will need those libs too. Note that if we use the application server’s default JSF implementation, we don’t have to add these either to the EAR or to the WAR.

trinidad-api-1.2.*, trinidad-impl-1.2.*

We’re using Trinidad, and ExtVal offers some Trinidad-specific features through the “Trinidad support” extension. In that case, the Trinidad libraries should be in the EAR too.

commons-*.jar

Various libraries that we just mentioned depend on one or more libraries from the Apache Commons project. They should also be moved to the EAR file to be sure that no class-loading errors occur.

Note that the aforementioned changes in our project structure are necessary only because we chose to have our Model layer in a separate JAR file. In smaller projects, it is often the case that the whole project is deployed as a single WAR file without enclosing it in an EAR. If we had chosen that strategy, no changes to the structure would have been necessary and we could have added all of the libraries to the WAR file, as we would do with any other library.

Other than including the necessary libraries as discussed before, no configuration is needed to get started with ExtVal. ExtVal uses the convention over configuration pattern extensively. That means, a lot of sensible defaults are chosen, and as long as we’re satisfied with the defaults, no configuration is needed. The next section will get us started with some basic ExtVal usage.

Bug with Trinidad tables
There’s a bug in ExtVal that can cause some weird behavior in Trinidad’s <tr:table> component. Only the first row will be populated with data, and other rows will not show any data. This happens only when a Facelets composite component is used to add the columns to the table—exactly what we do in our example application. The bug can be found in the JIRA bug tracker for ExtVal at https://issues.apache.org/jira/browse/EXTVAL-77.. There’s a workaround for the bug that we can use until it gets fixed. Be warned that this workaround may have other side effects.
This workaround is shown in the following code snippet, in which we have created a class called DevStartupListener:

public class DevStartupListener extends AbstractStartupListener {
@Override
protected void init() {

ExtValContext.getContext().addGlobalProperty(ExtValRendererProxy.KEY, null, true);
}
}

The required imports are in the org.apache.myfaces.extensions.validator.core package and subpackages. Register this class as a phase listener in the faces-config.xml file:

<lifecycle>
<phase-listener>inc.monsters.mias.workaround.DevStartupListener</phase-listener>

</lifecycle>

You’re all set, and the <tr:table> will now act as expected. Don’t forget to remove this workaround if the bug gets fixed in a future release of ExtVal.

Basic usage

After setting up ExtVal, the basic usage is very simple. Let’s explore a simple example in our MIAS application. In our Kid.java entity, we have some JPA annotations that map the properties of the Kid bean to a database table. Let’s take a closer look at the lastName property of our Kid bean:

@Column(name = "LAST_NAME", nullable = false, length = 30)
private String lastName;

The @Column annotation maps the lastName property to the LAST_NAME column in the database. It also shows some information that is derived from the table definition in the database. nullable = false means the database won’t accept an empty value in this field, and length = 30 means that no more than 30 characters can be stored in the corresponding database column. This information could be used for validation in our View layer. If we hadn’t used ExtVal, we would have added a required=”true” attribute to the input element in our EditKid.xhtml page. We also would have added a <tr:validateLength > component to the input component, or we could have set the maximumLength attribute. But all of these things would have been a duplication of information and logic, and would thus break the DRY principle.

With ExtVal, we don’t have to duplicate this information anymore. Whenever ExtVal encounters a nullable = false setting, it will automatically add a required=”true” attribute to the corresponding input element. In the same way, it will translate the length = 30 from the @Column annotation into a maximumLength attribute on the input component. The next screenshot shows ExtVal in action. (Note that all validators, and the required and maximumLength attributes were removed from the JSF code before the screenshot was taken.) The really nice thing about this example is that the validations created by ExtVal make use of Trinidad’s client-side validation capabilities. In other words, the error message is created within the user’s web browser before any input is sent to the server.

Apache MyFaces 1.2 Web Application Development

Complementing JPA annotations

It’s nice that we can reuse our JPA annotations for validation. But the chances are that not all validation that we want can be expressed in JPA annotations. For that reason, ExtVal offers a set of extra annotations that we can add to our beans to complement the implicit validation constraints that ExtVal derives from JPA annotations. These annotations are a part of the myfaces-extval-propertyvalidation-1.2.x.jar library. For example, if we want to add a minimum length to the lastName fi eld, we could use the @Length annotation as follows:

@Length(minimum = 5)

@Column(name = "LAST_NAME", nullable = false, length = 30)
private String lastName;

Note that if, for some reason, we couldn’t use the length = 30 setting on the @Column annotation, the @Length annotation also has a maximum property that can be set. The @Length annotation can be imported from the org.apache.myfaces.extensions.validator.baseval.annotation package, which is where the other annotations that ExtVal offers are also located. The following image shows the minimum length validation in action:

Apache MyFaces 1.2 Web Application Development

As the example in the screenshot shows, setting a minimum input length of five characters for a name might not be a good idea. However, that’s an entirely different discussion

Using ExtVal annotations for standard JSF validators

For each of the validator components that is a part of the JSF standard, there is an annotation in ExtVal’s Property Validation library. These are covered briefly in the following subsections.

Note that ExtVal will automatically use any overridden versions of the standard validators, if they are present in the project.

Defining length validation

For the length validation of input strings, the @Length annotation can be used, as shown in the previous example. This annotation relies on the javax.faces.validator.LengthValidator to implement the validation. The following table lists the available properties:

Property

Type

Explanation

minimum

int

The minimum length (inclusive) in characters of the input string

maximum

int

The maximum length (inclusive) of the input string in characters

Defining double range validation

To validate if a double value is within a certain range, the @DoubleRange annotation can be used, which delegates the implementation of the validation to the javax.faces.validator.DoubleRangeValidator validator. See the following table for the available properties:

Property

Type

Explanation

minimum

double

The minimum value (inclusive) of the double input

maximum

double

The maximum value (inclusive)of the double input

Defining long range validation

What @DoubleRange annotation does for doubles, the @LongRange annotation does for long values. It uses javax.faces.validator.LongRangeValidator for the implementation:

Property

Type

Explanation

minimum

long

The minimum value (inclusive) of the long input

maximum

long

The maximum value (inclusive) of the long input

Defining required fields

The example given at the beginning of this section showed how ExtVal can create a required=”true” attribute based on an @Column annotation with the nullable = false setting. If it is not possible to use this setting, ExtVal also has an alternative @Required annotation . Just add this annotation to a field to make it required

Using ExtVal’s additional annotations

Apart from the annotations that correspond to the standard JSF validators, some additional annotations exist in the Property Validation module that perform other validations. These are listed in the following subsections.

Whereas the validations based on the JSF standard validators use the error messages provided by the JSF validators, the additional validations cannot use standard messages from JSF. Therefore, standard messages are provided by ExtVal. Should you want to use your own message, all additional annotations have a validationErrorMsgKey property that can be used to assign a message key for the error message. We’ll discuss custom error messages in more detail later in this article.

Defining pattern-based validation

Validation with regular expressions is very powerful, and is very usable for validating phone numbers, postal codes, tax numbers, and any other data that has to fit in a certain pattern. Regular expression-based validation can be added by using the @Pattern annotation. For example, to allow only letters and spaces in the firstName field, we could write:

@Pattern(value="[A-Za-z ]*")
@Column(name = "FIRST_NAME", nullable = false, length = 30)

private String firstName;

For completeness, the following table lists the arguments of the @Pattern annotation:

Property

Type

Required

Explanation

value

String[]

Required

Array of regular expression patterns. Beware if you add more than one pattern that the input must match all patterns. It is easy to make any input invalid by using two patterns that are mutually exclusive.

validatonErrorMsgKey

String

Optional

Optional key for alternative error message.

LEAVE A REPLY

Please enter your comment!
Please enter your name here