Customizing and Extending Apache MyFaces ExtVal

Exclusive offer: get 50% off this eBook here
Apache MyFaces 1.2 Web Application Development

Apache MyFaces 1.2 Web Application Development — Save 50%

Building next-generation web applications with JSF and Facelets

$26.99    $13.50
by Bart Kummel | March 2010 | Java Web Development

This article by Bart Kummel, author of Apache MyFaces 1.2 Web Application Development, discusses how we can extend ExtVal by creating our own custom validation strategy. This article is a follow up on Apache MyFaces Extensions Validator, an article by the same author that is an introduction to ExtVal.

The ExtVal framework is very extensible, and extending it is fairly simple. The framework uses the convention over configuration paradigm. This means that if we’re happy with the conventions of the framework, we don’t have to configure anything. As an example of the extensibility of ExtVal, in this section we’re going to change the default behavior of ExtVal’s @Pattern annotation.

The @Pattern annotation accepts an array of Strings for the value argument. This means that more than one regular expression can be used to validate the input. By default, all regular expressions have to be matched in order for an input string to be valid. For example, if the patterns [A-Z].S* and [A-Za-z]* are combined, this effectively means that only words starting with a capital letter and containing only the characters a through to z, which may or may not be in capitals, are allowed. Note that this can be achieved with one single expression too—[A-Z].[A-Za-z]*.

Although combining two regular expressions with an “and” relation might be useful sometimes, having multiple expressions where only one of them has to be matched can be quite powerful too. We can think of a list of patterns for various (international) phone number formats. The input would be valid if one of the patterns is matched. The same can be done for postal codes, social security codes, and so on. So let’s see how we can change the behavior of ExtVal to achieve this

Implementing a custom validation strategy

ExtVal uses the concept of Validation Strategy for every type of validation. So, if an @Pattern annotation is used, ExtVal will use a PatternStrategy to execute the validation. We can implement our own ValidationStrategy to override the functionality of ExtVal’s standard PatternStrategy. The easiest way to do this is to create a subclass of AbstractAnnotationValidationStrategy <Pattern>:

package inc.monsters.mias.extval;


import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import org.apache.myfaces.extensions.validator.baseval.annotation.Pattern;

import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
import org.apache.myfaces.extensions.validator.core.validation.strategy.AbstractAnnotationValidationStrategy;

public class PatternOrValidationStrategy extends AbstractAnnotationValidationStrategy<Pattern> {

@Override
protected String getValidationErrorMsgKey(Pattern annotation) {
return annotation.validationErrorMsgKey();
}

@Override
protected void processValidation(FacesContext facesContext, UIComponent uiComponent, MetaDataEntry metaDataEntry, Object convertedObject) throws ValidatorException {


Pattern annotation = metaDataEntry.getValue(Pattern.class);
boolean matched = false;
String expressions = null;

for (String expression : annotation.value()) {
if (convertedObject != null && java.util.regex.Pattern.compile(expression).matcher(convertedObject.toString()).matches()) {

matched = true;
break;
} else {
 if (expressions == null) {
expressions = expression;
} else {
expressions += ", " + expression;

}
}
}
if(!matched) {
FacesMessage fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, getErrorMessageSummary(annotation), getErrorMessageDetail(annotation).replace("{0}",expressions));

throw new ValidatorException(fm);
}
}
}

The most important part of this class is, of course, the processValidation() method. This uses the MetaDataEntry object to access the annotation that defines the validation. By calling annotation.value(), the array of Strings that was set in the @Pattern annotation’s value attribute is obtained. By iterating over that array, the user input (convertedObject.toString()) is matched against each of the patterns. If one of the patterns matches the input, the boolean variable matched is set to true and the iteration is stopped. A ValidatorException is thrown if none of the patterns matches the input. The else branch of the outer if statement is used to create a list of patterns that didn’t match. That list is appended to the error message if none of the patterns matches.

Now that we’ve created our own custom validation strategy, we will have to tell ExtVal to use that instead of the default strategy for the @Pattern annotation. The next section shows how to do that.

Configuring ExtVal to use a custom validation strategy

The most straightforward way to configure a custom Validation Strategy in ExtVal is to write a custom Startup Listener that will add our Validation Strategy to the ExtVal configuration. A Startup Listener is just a JSF PhaseListener with some specific ExtVal functionality—it deregisters itself after being executed, thus guaranteeing that it will be executed only once. We can simply subclass ExtVal’s AbstractStartupListener. That way, we don’t have to implement much ourselves:

package inc.monsters.mias.extval;

import org.apache.myfaces.extensions.validator.baseval.annotation.Pattern;

import org.apache.myfaces.extensions.validator.core.ExtValContext;
import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticConfigurationNames;
import org.apache.myfaces.extensions.validator.core.initializer.configuration.StaticInMemoryConfiguration;

import org.apache.myfaces.extensions.validator.core.startup.AbstractStartupListener;

public class PatternOrStartupListener extends AbstractStartupListener {

@Override
protected void init() {


// 1.
StaticInMemoryConfiguration config = new StaticInMemoryConfiguration();

// 2.
config.addMapping(Pattern.class.getName(), PatternOrValidationStrategy.class.getName());


// 3.
ExtValContext.getContext().addStaticConfiguration(StaticConfigurationNames.META_DATA_TO_VALIDATION_STRATEGY_CONFIG, config);
}
}

There are three important steps here, which tie up with the numbers in the previous code:

  1. Create a new StaticInMemoryConfiguration object.
  2. Add a mapping to the StaticInMemoryConfiguration object. This maps the @Pattern annotation to our own PatternOrValidationStrategy validation strategy implementation. The addMapping() method expects two Strings, each containing a fully qualified class name. The safest way to get these class names is to use class.getName() because that will work even if the class is moved to another package. This step actually maps the @Pattern annotation to the PatternOrValidationStrategy.
  3. The created StaticInMemoryConfiguration object has to be added to the ExtValContext to become effective.

Note that we don’t implement the usual PhaseListener methods here. They are already implemented by the AbstractStartupListener. The last thing that we have to do is to add this Startup Listener to our faces-config.xml file as an ordinary PhaseListener, as follows:

<phase-listener>inc.monsters.mias.extval.PatternOrStartupListener</phase-listener>

Mapping an annotation to a validation strategy is one of the many name mappings that are performed inside the ExtVal framework. ExtVal implements its own NameMapper mechanism for all mappings that are performed inside the framework. As with nearly every part of ExtVal, this NameMapper mechanism can be overridden if desired. See also the Extending ExtVal in many other ways section.

Using alternative configuration add-ons

Although implementing a custom Startup Listener is fairly simple, it might not be the most ideal way to configure ExtVal—especially if a lot of configuration changes have to be made. The author of ExtVal has created two add-ons for ExtVal that provide alternative ways to configure ExtVal. Those add-ons are not apart of the ExtVal project. The author of ExtVal provides them as examples, but no support is available for them. If they fit your needs, you can use them. If not, you can use them as a starting point to implement your own configuration add-on.

  • One alternative is the annotation-based configuration. In this case, custom implementations can be annotated with special annotations, and should be put in a special base package. At application startup, the base package will be scanned for annotations, and the found annotations will be used to create the necessary configuration. See the Extending ExtVal with add-ons section for the download location, and installation instructions for this add-on. Some basic usage documentation is provided at http://os890.blogspot.com/2008/10/myfaces-extval-config-extension.html.
  • One alternative is the annotation-based configuration. In this case, custom implementations can be annotated with special annotations, and should be put in a special base package. At application startup, the base package will be scanned for annotations, and the found annotations will be used to create the necessary configuration. See the Extending ExtVal with add-ons section for the download location, and installation instructions for this add-on. Some basic usage documentation is provided at http://os890.blogspot.com/2008/10/myfaces-extval-config-extension.html.

Testing the custom validation strategy

Now that we’ve implemented our custom Validation Strategy, let’s do a simple test. For example, we could add the @Pattern annotation to the firstName property of the Kid class, as follows:

@Column(name = "FIRST_NAME")
@Pattern(value={"[A-Za-z]*", "[0-9]*"})
private String firstName;

In this case, “Shirley” would be valid input, as would be “4623”. But “Shirley7” wouldn’t be valid, as none of the regular expressions allow both letters and digits. If we had used the default PatternStrategy, no valid input for the firstName field would be possible, as the regular expressions in this example exclude each other

Of course this test case is not very useful. As mentioned before, having different patterns where only one of them has to be matched can be very useful for different (international) phone number formats, postal codes, social security codes, and so on. The example here is kept simple in order to make it easy to understand what input will match and what input won’t match.

Apache MyFaces 1.2 Web Application Development Building next-generation web applications with JSF and Facelets
Published: March 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Extending ExtVal in many other ways

Implementing a custom Validation Strategy is just one example of the many concepts in ExtVal that can be overridden by implementing a custom subclass, albeit one of the most useful ones. Here’s a list of other concepts in ExtVal that can be overridden:

  • StartupListener can be used to perform various actions at startup, such as registering any overridden ExtVal class. See the example in the Configuring ExtVal to use a custom Validation Strategy section.
  • ValidationStrategy can be used to customize the validation behavior, as discussed in the previous section. The easiest way to implement this interface is to subclass one of the abstract classes provided by ExtVal
  • MessageResolver can be used to customize the error messages.
  • ComponentInitializer allows the initialization of components before they are rendered. This can be used, for example, to add special client-side validation behavior to components.
  • MetaDataTransformer transforms constraints to an independent format so a component initializer doesn’t have any knowledge about the annotation used. A detailed explanation of this mechanism can be found in the Empower the Client section of an article about ExtVal on JSF Central, at http://jsfcentral.com/articles/myfaces_extval_3.html .
  • MetaDataExtractionInterceptor allows on-the-fly manipulation of metadata.
  • InformationProviderBean makes it possible to customize name conventions.
  • ProcessedInformationRecorder can be used to capture values after they are converted by JSF. For example, the ExtVals implementation of cross validation is based on this mechanism.
  • RendererInterceptor is one of the base mechanisms of ExtVal that is used to intercept renderers. All methods of javax.faces.render.Renderer can be intercepted.
  • NameMapper is used extensively throughout the ExtVal framework, in order to map sources to targets. In most cases, names are mapped; for example, annotation names are mapped to validation strategy names.
  • ExtVal makes extensive use of the Factory design pattern, and comes with a lot of factories that can be used when extending ExtVal. It is also possible to override the default factories as a way of changing ExtVal’s behavior. An overview of all of the factories can be found in the org.apache.myfaces.extensions.validator.core.factory.FactoryNames class in the ExtVal sources.

This list can be used as a starting point for exploring the extension opportunities in ExtVal. Some more information can be found on the ExtVal wiki at http://wiki.apache.org/myfaces/Extensions/Validator/DevDoc and http://wiki.apache.org/myfaces/Extensions/Validator/ConceptOverview.

Extending ExtVal with add-ons

ExtVal is a very flexible framework that was built with the possibility to extend it in mind. As we saw in the previous section, the ExtVal framework is full of hooks that can be a starting point for extending it. Of course, because it is an open source framework, anyone has the opportunity to extend and modify the framework to fit his needs. This can be a challenging job, even for advanced programmers. Everyone who has the time and knowledge should be encouraged to do so, as they can help in improving and expanding the ExtVal framework, or any other part of MyFaces. However, this section will focus on an easier way to expand the possibilities of the ExtVal framework: by using add-ons.

Getting add-ons for ExtVal

As ExtVal is a relatively new project and is not yet widely used, there are currently no “third party” open source add-ons for ExtVal. However, the lead developer of the ExtVal project has created some very useful add-ons. The following tables give an overview of the ExtVal add-ons that are available at the time of writing of this article. Keep an eye on the weblog of ExtVal’s lead developer for the latest news about add-ons—http://os890.blogspot.com/.

Add-on name

Annotation-based configuration

Description

Change ExtVal's defaults by using annotations instead of creating a startup listener. See the description in the Using alternative configuration add-ons section.

Documentation

http://os890.blogspot.com/2008/10/myfaces-extval-config-extension.html

Download

http://os890-m2-repository.googlecode.com/svn/tags/os890/at/gp/web/jsf/e...

Add-on name

Google Guice style configuration

Description

Change ExtVal's defaults by using Google Guice style configuration code. See the description in the Using alternative configuration add-ons section.

Documentation

http://os890.blogspot.com/2009/09/myfaces-extval-java-config-extension.html

Download

http://os890-m2-repository.googlecode.com/svn/tags/os890/at/gp/web/jsf/e...

Add-on name

Advanced metadata

Description

This is actually a collection of four add-ons that have something to do with constraint metadata. This add-on can be used to:

  • Conditionally exclude constraints from validation.

  • Force priorities for certain constraints by adding special metadata.

  • Add "virtual" metadata to non-ExtVal constraints. An example of the usage of this add-on can be found in the Setting the severity level on any constraint section at the end of this chapter.

Separate metadata from the main entity class.

Documentation

Download

http://os890-m2-repository.googlecode.com/svn/trunk/os890/at/gp/web/jsf/...

Add-on name

Secured Action

Description

This add-on shows that ExtVal can be used for things that go beyond input validation. It can be used to annotate JSF action methods, so that they can only be executed if certain security rules are met.

Documentation

http://os890.blogspot.com/2009/04/myfaces-extval-add-on-securedaction.html

Download

http://os890-m2-repository.googlecode.com/svn/tags/os890/at/gp/web/jsf/e...

Add-on name

Continue with warnings

Description

This add-on enables us to give certain constraint violations a "warning" severity level, and give the user the possibility to ignore the warning. The usage of this add-on is discussed in the Using payloads to set severity levels section.

Documentation

The Using payloads to set severity levels section and http://os890.blogspot.com/2009/10/add-on-customizable-severity-feature.html

Download

http://os890-m2-repository.googlecode.com/svn/trunk/os890/at/gp/web/jsf/...

Note that all of the add-ons mentioned here are hosted on the “os890” Maven repository. Two different root paths are used for the add-ons. The path starting with http://os890-m2-repository.googlecode.com/svn/trunk/os890 is the location for add-ons that work only with snapshot releases of ExtVal. Once a new stable version of ExtVal is released, we can expect these plugins to move to the other path in the Maven repository where all plugins that work with the stable versions of ExtVal are located, which is the URL starting with http://os890-m2-repository.googlecode.com/svn/tags/os890. If we were using Maven, we could have used these two URLs as Maven repositories and let Maven download the add-ons and install them.

More cutting-edge add-ons for adventurous people

As stated above, the add-ons listed here are all available via the “os890” Maven repository. Should you want to look for even more add-ons, and if you are prepared to compile them from the source code yourself, the source code repository of the “os890” project is an interesting place to visit. You can find it at http://code.google.com/p/os890/source/browse/#svn/trunk/java/web/jsf/extval.

Installing ExtVal add-ons

Installing an ExtVal add-on is simple. We only have to add the downloaded JAR to the shared lib directory in which all other ExtVal JARs are located, in our EAR file. If we have an application that is deployed as a single WAR file, we could simply add the JARs to the deployed libraries of that WAR file. This is all there is to do to install an ExtVal add-on. Note that each add-on has its specific usage instructions. Refer to the documentation that is linked to in the tables in the previous section.

Summary

In this article, we saw how we can customize and extend ExtVal in various ways.


If you have read this article you may be interested to view :


Apache MyFaces 1.2 Web Application Development Building next-generation web applications with JSF and Facelets
Published: March 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Bart Kummel

Bart Kummel is an experienced Java EE developer and architect living in The Netherlands. He studied Electrical Engineering at the Delft University of Technology and graduated with honor from the Hogeschool van Amsterdam, with a specialization in Technical Computer Sciences. After his study, he started as a developer of embedded software for a security systems manufacturer in Amsterdam. After four years of developing embedded software, Bart switched to enterprise software and started at Transfer Solutions B.V., based in Leerdam. Transfer Solutions is a consulting company that specializes in Oracle and Java technology.

As a consultant for Transfer Solutions, Bart gained a lot of experience with Java EE. For different clients, he has fulfilled the roles of developer or architect in small as well as large projects. In those projects, he has worked with various frameworks and standards, including Oracle’s Application Development Framework (ADF), Apache MyFaces, EclipseLink, JavaServer Faces (JSF), Java Persistence API (JPA), and Java Messaging Service (JMS). Bart also teaches courses in Object Orientation, UML, Java, Java EE, and ADF, at Transfer Solutions’ education department.

Bart published an article on EclipseLink in the Dutch Java Magazine, and presented the use of AJAX capabilities in Oracle’s ADF Faces at the ODTUG Kaleidoscope conference in 2007.

The link to his website is www.bartkummel.net

Books From Packt


iReport 3.7
iReport 3.7

Joomla! 1.5: Beginner's Guide
Joomla! 1.5: Beginner's Guide

NetBeans Platform 6.8 Developer's Guide
NetBeans Platform 6.8 Developer's Guide

jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

Firebug 1.5: Editing, Debugging, and Monitoring Web Pages
Firebug 1.5: Editing, Debugging, and Monitoring Web Pages

CMS Made Simple 1.6: Beginner's Guide
CMS Made Simple 1.6: Beginner's Guide

Grok 1.0 Web Development
    Grok 1.0 Web Development

Drupal 6 Attachment Views
Drupal 6 Attachment Views


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
k
4
p
P
7
2
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software