JSF Central - Metadata based validation for JavaServer Faces – Part 3
JSF Central

 
 Home 
 
 Products 
 
 Articles & Books 
 
 Resources 
Metadata based validation for JavaServer Faces
 
Metadata based validation for JavaServer Faces – Part 3
by Gerhard Petracek
17 Dec 2009 01:00 PST

In the third installment of this series on MyFaces ExtVal, Gerhard Petracek explains how to validate custom annotations, annotation based client-side validation, and zero configuration in MyFaces ExtVal.


The second part of this series about MyFaces ExtVal introduced the standard annotations provided by the framework itself, as well as some mechanisms to bypass validation. The standard annotations are nice, but most of the time you will face requirements that can only be implemented with custom constraints. This part covers how to validate these custom annotations, as well as annotation based client-side validation. I’ll also introduce zero configuration in MyFaces ExtVal, and type-safe configuration alternatives.

Annotations to constrain them all

First of all, it’s important to keep in mind that you decide how to implement your constraints. Please think about that again. It’s really up to you how the design of your constraints will look, or if you would like to validate existing implementations. The third release of MyFaces ExtVal will provide a JSR 303 (Bean Validation)adapter. In comparison to ExtVal constraints or your custom constraints, JSR 303 defines specific requirements for constraints. In future articles, we will take a closer look at the upcoming JSR 303 support. For now we concentrate on your (existing) constraints.

MyFaces ExtVal offers one validation module that is bundled with every release. Beyond this module, os890 (a Google Code project for open source case and feasibility studies as well as short examples) offers an additional module for dynamic property validation that provides dynamic constraints based on constraint aspects. One part of the module is @EMail. Since it is just implemented as a dynamic constraint, we will implement a static version of it, so you can use this example with every ExtVal release.

Let’s start with the easiest case, which you can see in Figure 1.

  Figure 1 shows a simple custom constraint
Figure 1 shows a simple custom constraint

As you can see, ExtVal doesn’t introduce any requirements. So, for instance, if your architect requires a strict separation between the model and 3rd party libraries during development, you won’t be introducing an additional dependency to your domain model. If your requirements are very strict and you aren’t even allowed to add custom constraints that might be used by a view-layer specific validation framework like ExtVal, os890 hosts an add-on that allows you to implement a meta-data provider class. The constraints provided by such a class are decoupled from the model itself and get merged with the target class at runtime.

However, let’s continue with our simple custom constraint. The annotation itself is nice, and you can use it like every other annotation, but currently you haven’t told ExtVal how to validate this new constraint. There are several ways to do that. You can plug in your own mechanism that introduces custom mechanisms for the validation process, or you can use the infrastructure provided by ExtVal. Here we use the provided infrastructure. The minimum requirement to do this is to implement the ValidationStrategy interface. However, it isn’t that convenient to use this interface directly. Therefore ExtVal offers abstract classes that provide an easy to use and powerful implementation. An example of such a class is AbstractValidationStrategy.

But let’s stop here for a moment. Maybe, you already have a JSF Validator that implements the validation logic or you would like to continue to implement mainly against the JSF interfaces. For example, let’s assume you already have implemented a JSF Validator that is called EMailValidator. All you have to do is delegate the work to an existing implementation that does all the work and is able to use all the JSF or custom mechanisms you have used so far. Figure 2 shows the required implementation.

  Figure 2 shows a simple adapter for a standard JSF validator
Figure 2 shows a simple adapter for a standard JSF validator

That’s it –- it’s really easy and straightforward! But wait -- we still haven’t told ExtVal that it should use our validation strategy for @EMail. Well, there are several ways to do that. Currently we are using one of the out-of-the-box conventions (the same package and the annotation name + “ValidationStrategy”). However, ExtVal also provides other conventions, including the option of introducing your own naming convention as well as a Java API to manually register a mapping. This optional API is quite powerful. For instance,the annotation based config add-on , as well as the java based config add-on hosted at os890, uses it to introduce type-safe mappings via annotations or a simple Java API inspired by Google Guice. Demo 104 and Demo 010 are short examples which introduce the usage of these add-ons.

So far we’ve created (or reused) a plain annotation and we wrote an adapter for an existing JSF Validator. At this point you might ask: “My error message contains a placeholder for the label and I just wrote an adapter for a JSF validator. Can I still replace the placeholder with the value of the label?” The answer is yes! The implementation of AbstractValidationStrategy offers several additional mechanisms: optional Validator initialization, labeled faces messages, and validation exception interception.

If you are familiar with the restrictions of other JSF validation frameworks, you might already love ExtVal -- and there are many more features available. One of them is an out-of-the-box pluggable mechanism for message resolving. In this case we don’t talk about message interpolation or anything like that (you can easily implement your own abstract validation strategy to do that). Message resolving means that you can provide a custom resolver that returns a message for a given key. The resolver knows how to lookup the message in the message source. The default message source format is the Resource-Bundle format. However, it isn’t difficult to implement a resolver for a database, XML, or any other format. So let’s refactor our existing implementation so that we can use this mechanism.

For our annotation we would like to provide a default message and it should be possible to override this default. Figure 3 shows the changed annotation implementation.

  Figure 3 shows a constraint that provides an error message key
Figure 3 shows a constraint that provides an error message key

The implementation of a message resolver is optional. As you have seen so far you can join the mechanisms of JSF (if available) or you can use the infrastructure provided by MyFaces ExtVal. In this case we would like to use the given infrastructure. So we have to use the AbstractAnnotationValidationStrategy (a subclass of AbstractValidationStrategy). Moreover, let’s assume that the JSF Validator allows us to inject the message. Figure 4 shows the refactored version.

  Figure 4 shows an adaptor that transfers the error message to the JSF Validator
Figure 4 shows an adaptor that transfers the error message to the JSF Validator

This version is available in the third release of ExtVal. (In the previous versions the same methods are available, but you have to cast to the target type.) As you can see it’s straightforward as well. Just use the inherited method getValidationErrorFacesMessage. After that you inject the result into the validator. Then, to use the message resolver mechanism of ExtVal you just have to implement the method getValidationErrorMsgKey, which allows you to return the message provided by the current annotation. ExtVal doesn’t require a special attribute name that provides the error message (key). This allows you to re-use existing annotations. If your constraints follow a naming convention for the error message attribute, you can easily implement an abstract class that is aware of your custom convention.

In order to avoid confusion, I recommend that you use a stateless implementation style, as we have used it so far. If you would like to extract initialization tasks to the init method, or you have more than one possible validation error message, or similar requirements, you can just switch to a stateful implementation without any additional effort. By default ExtVal uses a name-mapping cache and no instance pool (as with everything else, you can change even that if needed).

Hint: Maybe you’ve been wondering about the MetaDataEntry, which is the only significant difference from the normal JSF Validator interface. Among other things, this entry provides information about the constraint as well as some other useful information you might need. Basically validation isn’t restricted to annotations. Also, while AbstractAnnotationValidationStrategy is aware of annotations, the MetaDataEntry is not aware of annotations.

Message resolving

If we reuse the default message resolving mechanisms of ExtVal, where do we have to put our messages? As always ExtVal supports several built-in possibilities, or you can customize it. One of the mechanisms uses the principle of “convention over configuration.” You can just create a message bundle with the package and name “org.apache.myfaces.extensions.validator.custom.validation_messages.properties”. After that, you can use the JSF conventions for summary and detail messages. For rapid prototyping, it might be annoying to switch between files, so the third release of ExtVal allows you to provide inline messages as well. However, I hope you will choose the clean key-based approach that allows internationalization. Using a special package might be OK for the beginning, but later you might wish to have all messages (validation messages, other JSF messages, and custom application messages) in one place, so ExtVal allows you to reuse custom bundles. The os890 project provides several examples that illustrate different possibilities of message resolving. You are free to choose your preferred approach or implement your custom mechanism.

Empower the Client

If you are using a component library like MyFaces Trinidad that supports client-side validation, you can use it along with ExtVal. ExtVal allows you to transform the information, such as in annotations, to a generic format. To put things together, you have to implement component initializers for your input components, so you have one transformer per constraint and one initializer per component library (or per component – since component initializers are global, it’s up to you). This indirection allows you to reduce the implementation effort. I’ll skip over some of the more obvious details here. Figure 5 shows the component-initialization concept.

  Figure 5 shows the concept of component-initialization
Figure 5 shows the concept of component-initialization

In our example the constraint is @EMail. The first step is performed via a so called Metadata-Transformer. Figure 6 shows the implementation of EMailMetaDataTransformer.

  Figure 6 shows a simple Metadata-Transformer implementation
Figure 6 shows a simple Metadata-Transformer implementation

The naming convention we are using here is [constraint name] + “MetaDataTransformer”. The implementation depends on your requirements. In this simple example we signal that e-mail validation should be performed, and afterwards we forward the error message. Since the type of the value is an Object, you can use the data structure of your choice.

The second step is performed via a component initializer. As always there are different approaches to register your custom implementation. Again we choose the naming convention. Since it’s a global and stateless mechanism, you can use the name: org.apache.myfaces.extensions.validator.custom.ComponentInitializer. As before, that’s OK for rapid prototyping. Normally you would use a custom startup listener and register the initializer via the ExtVal Java API, or you could use one of the config add-ons mentioned before, or any other 3rd party add-on that provides the same functionality. Figure 7 shows a simplified implementation of the custom component initializer for MyFaces Trinidad. In this case we assume that our JSF Validator also implements the org.apache.myfaces.trinidad.validator.ClientValidator interface of Trinidad.

  Figure 6 shows a simple ComponentInitializer implementation
Figure 6 shows a simple ComponentInitializer implementation

The ComponentInitializer uses the values from the MetaDataTransformer to add new client validators to the component. The validator should be wrapped in a wrapper class provided by MyFaces ExtVal (ExtValTrinidadClientValidatorWrapper) to avoid further overhead on the server side. Only the JavaScript code for client-side validation will be rendered to the client.

Hint: The 3rd release of ExtVal allows you to restrict client-side validation via a generic and type-safe validation parameter mechanism in a fine-grained manner.

The generic approach of MyFaces ExtVal allows you to implement client-side validation for component libraries that don’t support this mechanism out-of-the-box as well. In this case, you have to implement the client-side validation on your own.. The important point is that it’s quite easy to do that if you are using the existing infrastructure provided by MyFaces ExtVal.

Zero configuration

Out of the box, all features of MyFaces ExtVal are activated without configuration. So you just have to add the jar files to your project and use the annotations. You are free to deactivate mechanisms if you don’t need them. If a component library doesn’t offer special features, or if it does some special workarounds behind the scenes, the MyFaces ExtVal Core as well as a validation module of your choice (or your own) is required. Otherwise, a support module for the component library or the generic support module (also shipped with MyFaces ExtVal releases) is required. More details are available in the Wiki.

So there is no configuration! As we saw in the section above, MyFaces ExtVal provides conventions to map, for instance, a Validation Strategy to an annotation. If you don’t like the naming conventions, you can customize them or you can use an alternative approach. One possibility is the previously mentioned annotation-based config add-on. You just have to check out the add-on, build it via Maven and add the dependency to your project (the maven dependency or the jar-file itself). If you prefer to use your own configuration concept, you can take a look at the add-on to learn the details of the ExtVal Java API. The advantage of this annotation based approach is that it’s completely type-safe.

The add-on provides different annotations with overlapping functionality. For example, you can annotate your constraints to point to the validation strategy, or if you have to validate 3rd party annotations and you aren’t allowed to customize them (for example, JPA annotations), you can annotate the validation strategy to point to the constraint(s). A similar capability is available for message resolvers. In the previous section I mentioned that there are different options for setting up a message resolver. Besides a convention to provide a resolver per validation module, the annotation-based configuration approach is the easiest.

Figure 8 shows a custom validator that is bound to two different annotations: @Column and @Required.

  Figure 8 shows an example for the usage of the annotation based config add-on
Figure 8 shows an example for the usage of the annotation based config add-on

Figure 9 shows an example for a custom message resolver that is based on the default implementation of MyFaces ExtVal and points to an existing message bundle var name (or directly to the message bundle).

  Figure 9 shows an alternative approach to redirect message resolving
Figure 9 shows an alternative approach to redirect message resolving

You can see an example of this in demo104. Please note that the add-on just scans a specific package, but you can customize this behavior easily.

Summary

This third part of the MyFaces ExtVal article series demonstrates the easy use of custom constraints as well as client-side validation based on annotations. Due to the pluggable nature of MyFaces ExtVal, it’s possible to join existing client-side validation mechanisms of component libraries that provide client-side validation. Based on the infrastructure of MyFaces ExtVal, it’s easy to implement custom constraints and it’s possible to create a custom validation infrastructure based on the core of ExtVal. The ExtVal Core provides advanced mechanisms that allow you to integrate 3rd party validation engines easily. One example is the JSR 303 integration.

We also looked at a subset of the zero-configuration approach as well as alternative type-safe possibilities. You can introduce your own validation mechanisms and configuration approaches via the ExtVal-Java-API. In the next part I'll explain the message resolving mechanisms and other mechanisms such as validation exception interception.

Resources



RSS feed(all feeds)

The Editor's Desk
Podcasts
Inside Facelets
In the Trenches

Site version 1.83  Report web site problems

Copyright (C) 2003-2015 Virtua, Inc. All Rights Reserved. Java, JavaServer Faces, and all Java-based marks are trademarks or registered trademarks of Oracle Corporation. in the United States and other countries. Virtua, Inc. is independent of Oracle Corporation. All other trademarks are the sole property of their respective owners.